From: Tang Cheng Date: Mon, 22 Apr 2019 05:07:00 +0000 (+0800) Subject: 基本测试API认证,WebApp 认证,CSRF模块 X-Git-Tag: 1.0.0^2~268 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=5ef0576cbcce16137c4d1b7c6072851a592e02b1;p=epayment%2Ffood_payapi.git 基本测试API认证,WebApp 认证,CSRF模块 --- diff --git a/build.gradle b/build.gradle index d0275920..6c9b7199 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ dependencies { 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 3868edd3..c7f53601 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 javax.servlet.http.HttpServletResponse; 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 56782db7..c5c3f7ca 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.DefaultSecurityFilterChain; import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; import org.springframework.stereotype.Component; -@Component("validateCodeSecurityConfig") +//@Component("validateCodeSecurityConfig") public class ValidateCodeSecurityConfig extends SecurityConfigurerAdapter { @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 26d6ea54..74cc2403 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.*; 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 class VerifyCode { 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 7ff33c6c..580ee130 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.RedisPassword 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 @@ class AppConfig { } } +@Configuration +class HttpSessionConfig { + @Bean + fun sessionRedisTemplate( + connectionFactory: RedisConnectionFactory): RedisTemplate { + val template = RedisTemplate() + 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 cd7d60f5..3e13e8b1 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.HttpStatus 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 @@ class ApiAuthController { } @RestController -class ValidateCodeController{ +class ValidateCodeController { @GetMapping("/code/image") fun createCode(request: HttpServletRequest, response: HttpServletResponse) { @@ -113,6 +111,9 @@ class ValidateCodeController{ } } + +data class LoginForm(val username: String, val password: String, val imageCode: String) + @Controller class WebHomeController { @@ -121,4 +122,10 @@ class WebHomeController { @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 b5297148..29c795dc 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/security.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/security.kt @@ -2,10 +2,6 @@ package com.supwisdom.dlpay 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.annotation.web.configuration.WebSecur 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 @@ class WebSecurityConfig { @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 @@ class WebSecurityConfig { .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 0a248484..6abc8d8a 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.encoding=UTF-8 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 4feb52a3..919d862c 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -1,12 +1,15 @@ + 用户登录 + + + -