implementation 'org.postgresql:postgresql:42.2.5'
implementation 'com.jcabi:jcabi-manifests:1.1'
implementation 'org.bitbucket.b_c:jose4j:0.6.3'
+ implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
implementation 'org.springframework.social:spring-social-web:1.1.6.RELEASE'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
implementation group: 'com.sun.jersey', name: 'jersey-client', version: '1.19'
import java.io.IOException;\r
\r
\r
-@Component("validateCodeFilter")\r
-public class ValidateCodeFilter extends OncePerRequestFilter{\r
-\r
- /**\r
- * 校验失败处理器\r
- */\r
- @Autowired\r
- private AuthenticationFailureHandler myAuthenticationFailureHandler;\r
-\r
- /**\r
- * 校验成功处理器\r
- */\r
- @Autowired\r
- private AuthenticationSuccessHandler myAuthenticationSuccessHandler;\r
-\r
-\r
- @Override\r
- protected void doFilterInternal(HttpServletRequest request,\r
- HttpServletResponse response, FilterChain filterChain)\r
- throws ServletException, IOException {\r
- if (StringUtil.equals("/login/form", request.getRequestURI())\r
- && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {\r
- try {\r
- validate(request);\r
- } catch (ValidateCodeException e) {\r
- myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);\r
- }\r
- }\r
- filterChain.doFilter(request, response);\r
- }\r
-\r
- private void validate(HttpServletRequest request) throws ValidateCodeException {\r
- VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
- String inputCode;\r
- try {\r
- inputCode = request.getParameter("imageCode");\r
- } catch (Exception e) {\r
- throw new ValidateCodeException("获取验证码的值失败");\r
- }\r
- if (StringUtil.isEmpty(inputCode)) {\r
- throw new ValidateCodeException("验证码的值不能为空");\r
- }\r
- if (null == imageCode) {\r
- throw new ValidateCodeException("验证码不存在");\r
- }\r
- if (imageCode.isExpired()) {\r
- request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
- throw new ValidateCodeException("验证码已过期");\r
- }\r
- if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {\r
- throw new ValidateCodeException("验证码不匹配");\r
- }\r
- request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
- }\r
-\r
-}\r
+//@Component("validateCodeFilter")\r
+//public class ValidateCodeFilter extends OncePerRequestFilter{\r
+//\r
+// /**\r
+// * 校验失败处理器\r
+// */\r
+// @Autowired\r
+// private AuthenticationFailureHandler myAuthenticationFailureHandler;\r
+//\r
+// /**\r
+// * 校验成功处理器\r
+// */\r
+// @Autowired\r
+// private AuthenticationSuccessHandler myAuthenticationSuccessHandler;\r
+//\r
+//\r
+// @Override\r
+// protected void doFilterInternal(HttpServletRequest request,\r
+// HttpServletResponse response, FilterChain filterChain)\r
+// throws ServletException, IOException {\r
+// if (StringUtil.equals("/login/form", request.getRequestURI())\r
+// && StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {\r
+// try {\r
+// validate(request);\r
+// } catch (ValidateCodeException e) {\r
+// myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);\r
+// }\r
+// }\r
+// filterChain.doFilter(request, response);\r
+// }\r
+//\r
+// private void validate(HttpServletRequest request) throws ValidateCodeException {\r
+// VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
+// String inputCode;\r
+// try {\r
+// inputCode = request.getParameter("imageCode");\r
+// } catch (Exception e) {\r
+// throw new ValidateCodeException("获取验证码的值失败");\r
+// }\r
+// if (StringUtil.isEmpty(inputCode)) {\r
+// throw new ValidateCodeException("验证码的值不能为空");\r
+// }\r
+// if (null == imageCode) {\r
+// throw new ValidateCodeException("验证码不存在");\r
+// }\r
+// if (imageCode.isExpired()) {\r
+// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
+// throw new ValidateCodeException("验证码已过期");\r
+// }\r
+// if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {\r
+// throw new ValidateCodeException("验证码不匹配");\r
+// }\r
+// request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);\r
+// }\r
+//\r
+//}\r
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
import org.springframework.stereotype.Component;
-@Component("validateCodeSecurityConfig")
+//@Component("validateCodeSecurityConfig")
public class ValidateCodeSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain,HttpSecurity> {
@Autowired
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Random;
-public class VerifyCode {
+public class VerifyCode implements Serializable {
private int w = 100;
private int h = 35;
private Random r = new Random();
public boolean isExpired(){
return LocalDateTime.now().isAfter(localDateTime);
}
+
+
}
package com.supwisdom.dlpay
-import com.supwisdom.dlpay.framework.filter.ValidateCodeFilter
-import com.supwisdom.dlpay.framework.security.MyAuthenticationFailureHandler
-import com.supwisdom.dlpay.framework.security.MyAuthenticationSuccessHandler
import io.lettuce.core.ReadFrom
-import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.data.redis.connection.RedisStandaloneConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory
+import org.springframework.data.redis.core.RedisTemplate
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories
+import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer
+import org.springframework.data.redis.serializer.StringRedisSerializer
@Configuration
}
}
+@Configuration
+class HttpSessionConfig {
+ @Bean
+ fun sessionRedisTemplate(
+ connectionFactory: RedisConnectionFactory): RedisTemplate<Any, Any> {
+ val template = RedisTemplate<Any, Any>()
+ template.keySerializer = StringRedisSerializer()
+ template.hashKeySerializer = StringRedisSerializer()
+
+ template.setDefaultSerializer(GenericJackson2JsonRedisSerializer())
+ template.setConnectionFactory(connectionFactory)
+ return template
+ }
+}
+
+
@SpringBootApplication
class PayApiApplication
import org.springframework.http.ResponseEntity
import org.springframework.social.connect.web.HttpSessionSessionStrategy
import org.springframework.stereotype.Controller
-import org.springframework.web.bind.annotation.GetMapping
-import org.springframework.web.bind.annotation.RequestMapping
-import org.springframework.web.bind.annotation.RestController
+import org.springframework.web.bind.annotation.*
import org.springframework.web.context.request.ServletWebRequest
import java.util.*
import javax.imageio.ImageIO
}
@RestController
-class ValidateCodeController{
+class ValidateCodeController {
@GetMapping("/code/image")
fun createCode(request: HttpServletRequest, response: HttpServletResponse) {
}
}
+
+data class LoginForm(val username: String, val password: String, val imageCode: String)
+
@Controller
class WebHomeController {
@GetMapping("/login")
fun loginView() = "login"
+
+ @PostMapping("/login/form")
+ fun loginForm(form: LoginForm): String {
+ println(form.username)
+ return "index"
+ }
}
import com.supwisdom.dlpay.framework.core.JwtConfig
import com.supwisdom.dlpay.framework.core.JwtTokenUtil
-import com.supwisdom.dlpay.framework.filter.ValidateCodeFilter
-import com.supwisdom.dlpay.framework.security.MyInvalidSessionStrategy
-import com.supwisdom.dlpay.framework.security.ValidateCodeSecurityConfig
-import com.supwisdom.dlpay.framework.service.OperatorDetailService
import org.jose4j.jwt.consumer.InvalidJwtException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.security.config.http.SessionCreationPolicy
import org.springframework.security.core.authority.SimpleGrantedAuthority
import org.springframework.security.core.context.SecurityContextHolder
-import org.springframework.security.core.session.SessionRegistry
-import org.springframework.security.core.session.SessionRegistryImpl
-import org.springframework.security.core.userdetails.User
-import org.springframework.security.core.userdetails.UserDetailsService
-import org.springframework.security.provisioning.InMemoryUserDetailsManager
-import org.springframework.security.web.authentication.AuthenticationFailureHandler
-import org.springframework.security.web.authentication.AuthenticationSuccessHandler
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
-import org.springframework.security.web.session.InvalidSessionStrategy
-import org.springframework.security.web.session.SessionInformationExpiredStrategy
+import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.web.filter.OncePerRequestFilter
import javax.servlet.FilterChain
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
+import javax.sql.DataSource
class ApiJwtAuthenticationFilter(jwt: JwtTokenUtil) : OncePerRequestFilter() {
@Autowired
lateinit var jwtConfig: JwtConfig
+
override fun configure(http: HttpSecurity) {
// 设置 API 访问权限管理
- http.csrf().disable()
- .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterAfter(ApiJwtAuthenticationFilter(JwtTokenUtil(jwtConfig)),
UsernamePasswordAuthenticationFilter::class.java)
.antMatchers("/api/common/**").hasAnyRole("THIRD_COMMON", "THIRD_ADMIN")
.antMatchers("/api/consume/**").hasRole("THIRD_CONSUME")
.antMatchers("/api/deposit/**").hasRole("THIRD_DEPOSIT")
- .antMatchers("/api/user/**").hasAnyRole("THIRD_COMMON", "THIRD_ADMIN")
+ .antMatchers("/api/user/**").hasRole("THIRD_ADMIN")
.antMatchers("/api/shop/**").hasRole("THIRD_SHOP")
- // 注册 filter
+ .and()
+ .csrf().ignoringAntMatchers("/api/**")
}
}
@Configuration
class MvcWebSecurityConfigurationAdapter : WebSecurityConfigurerAdapter() {
@Autowired
- lateinit var validateCodeSecurityConfig: ValidateCodeSecurityConfig
- @Autowired
- lateinit var userDetailsService: OperatorDetailService
- @Autowired
- lateinit var myAuthenticationFailureHandler: AuthenticationFailureHandler
- @Autowired
- lateinit var myAuthenticationSuccessHandler: AuthenticationSuccessHandler
- @Autowired
- lateinit var myInvalidSessionStrategy: InvalidSessionStrategy
+ lateinit var dataSource: DataSource
+// @Autowired
+// lateinit var validateCodeSecurityConfig: ValidateCodeSecurityConfig
+// @Autowired
+// lateinit var userDetailsService: OperatorDetailService
+// @Autowired
+// lateinit var myAuthenticationFailureHandler: AuthenticationFailureHandler
+// @Autowired
+// lateinit var myAuthenticationSuccessHandler: AuthenticationSuccessHandler
+// @Autowired
+// lateinit var myInvalidSessionStrategy: InvalidSessionStrategy
+ @Bean
+ fun jdbcTokenImplement(): JdbcTokenRepositoryImpl {
+ return JdbcTokenRepositoryImpl().also {
+ it.setDataSource(dataSource)
+ }
+ }
+
override fun configure(http: HttpSecurity) {
// 设置 Web MVC 应用权限
- http.apply(validateCodeSecurityConfig)
+ http.csrf()
+ .and()
+ .authorizeRequests()
+ .antMatchers("/login", "/login/form").permitAll()
+ .antMatchers("/static/**").permitAll()
+ .antMatchers("/code/image").permitAll()
+ .anyRequest().authenticated()
+ .and()
+ .sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login/form")
- .successHandler(myAuthenticationSuccessHandler)
- .failureHandler(myAuthenticationFailureHandler)
.and()
.logout()
.logoutRequestMatcher(AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
- .and()
- .userDetailsService(userDetailsService)
- .authorizeRequests()
- .antMatchers("/login").permitAll()
- .antMatchers("/static/**").permitAll()
- .antMatchers("/code/image").permitAll()
- .anyRequest().authenticated()
- .and()
- .formLogin()
// 设置 Web MVC 应用权限
// http.apply(validateCodeSecurityConfig)
// .and()
#######################################springboot配置 start#################################
# 单库数据库配置
-spring.datasource.url=jdbc:oracle:thin:@172.28.201.101:47922:orcl
-spring.datasource.username=dlpay
-spring.datasource.password=kingstar
-spring.datasource.driver.class=oracle.jdbc.driver.OracleDriver
-spring.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
spring.jpa.show-sql=true
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.maximum-pool-size=5
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
spring.thymeleaf.enabled=true
-#################### Redis ####################
-# Redis settings
-redis.server=172.28.201.101
-redis.port=16379
-redis.password=kingstar
-redis.database=0
-#################### jwt ####################
-# jwt settings
-jwt.secret=Zj5taLomEbrM0lk+NMQZbHfSxaDU1wekjT+kiC3YzDw=
-jwt.expiration=3600
-jwt.header=payapi
\ No newline at end of file
<!DOCTYPE html>
+
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>用户登录</title>
+ <meta name="_csrf" th:content="${_csrf.token}" />
+ <!-- default header name is X-CSRF-TOKEN -->
+ <meta name="_csrf_header" th:content="${_csrf.headerName}" />
<link rel="stylesheet" type="text/css" th:href="@{/static/libs/layui/css/layui.css}" />
<link rel="stylesheet" type="text/css" th:href="@{/static/payapi/css/login.css}" />
</head>
-
<body>
<div class="login-wrapper">
<div class="layui-input-block">
<input name="username" type="text" lay-verify="required" placeholder="账号"
class="layui-input">
+ <input type="hidden"
+ th:name="${_csrf.parameterName}"
+ th:value="${_csrf.token}"/>
</div>
</div>
<div class="layui-form-item">