基本测试API认证,WebApp 认证,CSRF模块
diff --git a/build.gradle b/build.gradle
index d027592..6c9b719 100644
--- a/build.gradle
+++ b/build.gradle
@@ -40,6 +40,7 @@
     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'
diff --git a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
index 3868edd..c7f5360 100755
--- a/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/filter/ValidateCodeFilter.java
@@ -20,59 +20,59 @@
 import java.io.IOException;

 

 

-@Component("validateCodeFilter")

-public class ValidateCodeFilter extends OncePerRequestFilter{

-

-	/**

-	 * 校验失败处理器

-	 */

-	@Autowired

-	private AuthenticationFailureHandler myAuthenticationFailureHandler;

-

-	/**

-	 * 校验成功处理器

-	 */

-	@Autowired

-	private AuthenticationSuccessHandler myAuthenticationSuccessHandler;

-

-

-	@Override

-	protected void doFilterInternal(HttpServletRequest request,

-																	HttpServletResponse response, FilterChain filterChain)

-			throws ServletException, IOException {

-		if (StringUtil.equals("/login/form", request.getRequestURI())

-				&& StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {

-			try {

-				validate(request);

-			} catch (ValidateCodeException e) {

-				myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);

-			}

-		}

-		filterChain.doFilter(request, response);

-	}

-

-	private void validate(HttpServletRequest request) throws ValidateCodeException {

-		VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

-		String inputCode;

-		try {

-			inputCode = request.getParameter("imageCode");

-		} catch (Exception e) {

-			throw new ValidateCodeException("获取验证码的值失败");

-		}

-		if (StringUtil.isEmpty(inputCode)) {

-			throw new ValidateCodeException("验证码的值不能为空");

-		}

-		if (null == imageCode) {

-			throw new ValidateCodeException("验证码不存在");

-		}

-		if (imageCode.isExpired()) {

-			request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

-			throw new ValidateCodeException("验证码已过期");

-		}

-		if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {

-			throw new ValidateCodeException("验证码不匹配");

-		}

-		request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

-	}

-

-}

+//@Component("validateCodeFilter")

+//public class ValidateCodeFilter extends OncePerRequestFilter{

+//

+//	/**

+//	 * 校验失败处理器

+//	 */

+//	@Autowired

+//	private AuthenticationFailureHandler myAuthenticationFailureHandler;

+//

+//	/**

+//	 * 校验成功处理器

+//	 */

+//	@Autowired

+//	private AuthenticationSuccessHandler myAuthenticationSuccessHandler;

+//

+//

+//	@Override

+//	protected void doFilterInternal(HttpServletRequest request,

+//																	HttpServletResponse response, FilterChain filterChain)

+//			throws ServletException, IOException {

+//		if (StringUtil.equals("/login/form", request.getRequestURI())

+//				&& StringUtil.equalsIgnoreCase(request.getMethod(), "post")) {

+//			try {

+//				validate(request);

+//			} catch (ValidateCodeException e) {

+//				myAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);

+//			}

+//		}

+//		filterChain.doFilter(request, response);

+//	}

+//

+//	private void validate(HttpServletRequest request) throws ValidateCodeException {

+//		VerifyCode imageCode = (VerifyCode) request.getSession().getAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

+//		String inputCode;

+//		try {

+//			inputCode = request.getParameter("imageCode");

+//		} catch (Exception e) {

+//			throw new ValidateCodeException("获取验证码的值失败");

+//		}

+//		if (StringUtil.isEmpty(inputCode)) {

+//			throw new ValidateCodeException("验证码的值不能为空");

+//		}

+//		if (null == imageCode) {

+//			throw new ValidateCodeException("验证码不存在");

+//		}

+//		if (imageCode.isExpired()) {

+//			request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

+//			throw new ValidateCodeException("验证码已过期");

+//		}

+//		if (!StringUtil.equalsIgnoreCase(imageCode.getText(), inputCode)) {

+//			throw new ValidateCodeException("验证码不匹配");

+//		}

+//		request.getSession().removeAttribute(ImageCodeUtil.LOGIN_IMAGECODE_SESSIONKEY);

+//	}

+//

+//}

diff --git a/src/main/java/com/supwisdom/dlpay/framework/security/ValidateCodeSecurityConfig.java b/src/main/java/com/supwisdom/dlpay/framework/security/ValidateCodeSecurityConfig.java
index 56782db..c5c3f7c 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/security/ValidateCodeSecurityConfig.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/security/ValidateCodeSecurityConfig.java
@@ -9,7 +9,7 @@
 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
diff --git a/src/main/java/com/supwisdom/dlpay/framework/security/validate/VerifyCode.java b/src/main/java/com/supwisdom/dlpay/framework/security/validate/VerifyCode.java
index 26d6ea5..74cc240 100644
--- a/src/main/java/com/supwisdom/dlpay/framework/security/validate/VerifyCode.java
+++ b/src/main/java/com/supwisdom/dlpay/framework/security/validate/VerifyCode.java
@@ -5,10 +5,11 @@
 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();
@@ -120,4 +121,6 @@
   public boolean isExpired(){
     return LocalDateTime.now().isAfter(localDateTime);
   }
+
+
 }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
index 7ff33c6..580ee13 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/PayApiApplication.kt
@@ -1,10 +1,6 @@
 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
@@ -15,7 +11,10 @@
 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
@@ -49,6 +48,22 @@
     }
 }
 
+@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
 
diff --git a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
index cd7d60f..3e13e8b 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/framework/controller/security_controller.kt
@@ -15,9 +15,7 @@
 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
@@ -103,7 +101,7 @@
 }
 
 @RestController
-class ValidateCodeController{
+class ValidateCodeController {
 
     @GetMapping("/code/image")
     fun createCode(request: HttpServletRequest, response: HttpServletResponse) {
@@ -113,6 +111,9 @@
     }
 }
 
+
+data class LoginForm(val username: String, val password: String, val imageCode: String)
+
 @Controller
 class WebHomeController {
 
@@ -121,4 +122,10 @@
 
     @GetMapping("/login")
     fun loginView() = "login"
+
+    @PostMapping("/login/form")
+    fun loginForm(form: LoginForm): String {
+        println(form.username)
+        return "index"
+    }
 }
diff --git a/src/main/kotlin/com/supwisdom/dlpay/security.kt b/src/main/kotlin/com/supwisdom/dlpay/security.kt
index b529714..29c795d 100644
--- a/src/main/kotlin/com/supwisdom/dlpay/security.kt
+++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt
@@ -2,10 +2,6 @@
 
 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
@@ -19,21 +15,14 @@
 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() {
@@ -79,10 +68,10 @@
             @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)
@@ -91,50 +80,58 @@
                         .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()
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 0a24848..6abc8d8 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,10 +1,5 @@
 #######################################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
@@ -23,14 +18,3 @@
 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
diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html
index 4feb52a..919d862 100644
--- a/src/main/resources/templates/login.html
+++ b/src/main/resources/templates/login.html
@@ -1,12 +1,15 @@
 <!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">
 
@@ -25,6 +28,9 @@
                     <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">