From 7cc61baa2d9a5cc5605bbf666b1606384be5c1ec Mon Sep 17 00:00:00 2001 From: GPU is all you need <2778335106@qq.com> Date: Thu, 19 May 2022 20:41:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/ncst/award/config/SecurityConfig.java | 163 +++++++++--------- 1 file changed, 84 insertions(+), 79 deletions(-) diff --git a/awardBE/src/main/java/edu/ncst/award/config/SecurityConfig.java b/awardBE/src/main/java/edu/ncst/award/config/SecurityConfig.java index daae5c5..5954f97 100644 --- a/awardBE/src/main/java/edu/ncst/award/config/SecurityConfig.java +++ b/awardBE/src/main/java/edu/ncst/award/config/SecurityConfig.java @@ -1,16 +1,19 @@ package edu.ncst.award.config; +import cn.hutool.extra.spring.SpringUtil; import com.fasterxml.jackson.databind.ObjectMapper; -import edu.ncst.award.config.security.DataBaseUrlVoter; +import edu.ncst.award.config.security.CustomUserCache; import edu.ncst.award.config.security.filter.AuthCheckFilter; import edu.ncst.award.config.security.filter.LoginFilter; import edu.ncst.award.exception.CodeMsg; import edu.ncst.award.service.ILoginLogService; import edu.ncst.award.service.impl.system.UserServiceImpl; import edu.ncst.award.utils.ResultUtils; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCache; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDecisionVoter; @@ -26,8 +29,7 @@ import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.core.userdetails.cache.SpringCacheBasedUserCache; import org.springframework.security.web.access.expression.WebExpressionVoter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @@ -39,25 +41,23 @@ import java.util.List; * 安全配置 */ @Configuration +@Slf4j @EnableWebSecurity -@EnableGlobalMethodSecurity(securedEnabled=true) +@RequiredArgsConstructor +@EnableGlobalMethodSecurity(securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { - @Autowired - private UserServiceImpl userService; - @Autowired - private ILoginLogService loginLogService; - @Autowired - private DataBaseUrlVoter dataBaseUrlVoter; - @Autowired - private RedisTemplate redisCacheTemplate; + private final UserServiceImpl userService; + private final ILoginLogService loginLogService; + private final DataBaseUrlVoter dataBaseUrlVoter; + private final RedisTemplate redisCacheTemplate; /** * 认证失败处理类 */ - @Autowired - CustomAccessDeniedHandler accessDeniedHandler; + private final CustomAccessDeniedHandler accessDeniedHandler; //org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) + /** * 解决 无法直接注入 AuthenticationManager * @@ -66,17 +66,18 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { */ @Bean @Override - public AuthenticationManager authenticationManagerBean() throws Exception - { + public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** - * 权限白名单 + * 权限白名单' + * ' + *

* 注意:该名单下匹配的 URL 不会经过鉴权,因此也无法获取当前用户的信息 */ private final String[] WHITE_LIST = { - "/v2/api-docs", + "/v3/api-docs", "/configuration/ui", "/swagger-resources/**", "/configuration/**", @@ -95,20 +96,18 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { }; - - /** * 权限投票访问决策管理器 */ @Bean public AccessDecisionManager accessDecisionManager() { - List> decisionVoters + List> decisionVoters = Arrays.asList( new WebExpressionVoter(), new RoleVoter(),//主要用来判断当前请求是否具备该接口所需要的角色 dataBaseUrlVoter, new AuthenticatedVoter()); - return new UnanimousBased(decisionVoters);//要求所有 AccessDecisionVoter 均返回肯定的结果时,才代表授予权限。 + return new UnanimousBased(decisionVoters);//要求所有 AccessDecisionVoter 一票否决,所有弃权时deny } @Override @@ -116,7 +115,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setHideUserNotFoundExceptions(false); daoAuthenticationProvider.setUserDetailsService(userService); - daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder()); + daoAuthenticationProvider.setUserCache(new CustomUserCache(redisCacheTemplate)); + daoAuthenticationProvider.setPasswordEncoder(CustomDelegatingPasswordEncoder.createDelegatingPasswordEncoder()); auth.authenticationProvider(daoAuthenticationProvider); } @@ -135,68 +135,73 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { * rememberMe | 允许通过remember-me登录的用户访问 * authenticated | 用户登录后可访问 */ - //权限验证 基于资源配置 - // HttpSecurity 及WebSecurity 作用是不一样的: - // WebSecurity 主要针对的全局的忽略规则, - // HttpSecurity主要是权限控制规则。 -// @Override -// protected void configure(HttpSecurity http) throws Exception { -// -// //允许跨域 -// http.cors().and().anonymous().and() -// // CRSF禁用,因为不使用session -// .csrf().disable() -// .formLogin().disable().httpBasic().disable() -// .authorizeRequests() -// .accessDecisionManager(accessDecisionManager())//访问决策管理器 -// .antMatchers("/api/login").permitAll() -// .antMatchers("/system/init").permitAll() -// // 除上面外的所有请求全部需要鉴权认证 -// .anyRequest().authenticated() -// .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and() -// .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); -// -// http.addFilterAfter(new AuthCheckFilter(redisCacheTemplate), UsernamePasswordAuthenticationFilter.class) -// .addFilterAt( -// new LoginFilter(authenticationManager(), loginLogService, redisCacheTemplate), UsernamePasswordAuthenticationFilter.class -// ) -// .exceptionHandling()//登录认证失败 -// .authenticationEntryPoint(((request, response, authException) -> { -// response.setCharacterEncoding("utf-8"); -// response.setContentType("application/json;charset=utf-8"); -// -// PrintWriter out = response.getWriter(); -// out.write(new ObjectMapper().writeValueAsString(ResultUtils.error(CodeMsg.USER_NEED_LOGIN))); -// out.flush(); -// out.close(); -// })); -// -// // 退出登录 -// http.logout() -// .logoutUrl("/logout") -// .deleteCookies("JSESSIONID") -// .logoutSuccessHandler(((request, response, authentication) -> { -// PrintWriter out = response.getWriter(); -// response.setContentType("application/json"); -// out.write(new ObjectMapper().writeValueAsString(ResultUtils.success("注销成功"))); -// out.flush(); -// out.close(); -// })); -// } - - +// 权限验证 基于资源配置 +// HttpSecurity 及WebSecurity 作用是不一样的: +// WebSecurity 主要针对的全局的忽略规则, +// HttpSecurity主要是权限控制规则。 @Override - protected void configure(HttpSecurity httpSecurity) throws Exception{ - //调试阶段 - httpSecurity.csrf().disable().authorizeRequests(); - httpSecurity.authorizeRequests().anyRequest() - .permitAll().and().logout().permitAll(); + protected void configure(HttpSecurity http) throws Exception { + + //允许跨域 + http.cors().and().anonymous().and() + // CSRF禁用,因为不使用session + .csrf().disable() + .formLogin().disable() + .httpBasic().disable() + .authorizeRequests() + .accessDecisionManager(accessDecisionManager())//访问决策管理器 + .antMatchers("/api/login").permitAll() + .antMatchers("/system/init").permitAll() + // 除上面外的所有请求全部需要鉴权认证 + .anyRequest().authenticated() + .and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).and() + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); + + http.addFilterAfter(new AuthCheckFilter(redisCacheTemplate), UsernamePasswordAuthenticationFilter.class) + .addFilterAt(new LoginFilter(authenticationManager(), loginLogService, redisCacheTemplate), UsernamePasswordAuthenticationFilter.class) + .exceptionHandling()//登录认证失败 + .authenticationEntryPoint(((request, response, authException) -> { + response.setCharacterEncoding("utf-8"); + response.setContentType("application/json;charset=utf-8"); + + PrintWriter out = response.getWriter(); + out.write(new ObjectMapper().writeValueAsString(ResultUtils.error(CodeMsg.USER_NEED_LOGIN))); + out.flush(); + out.close(); + })); + + // 退出登录 + http.logout() + .logoutUrl("/logout") + .deleteCookies("JSESSIONID") + .logoutSuccessHandler(((request, response, authentication) -> { + PrintWriter out = response.getWriter(); + response.setContentType("application/json"); + out.write(new ObjectMapper().writeValueAsString(ResultUtils.success("注销成功"))); + out.flush(); + out.close(); + })); } + +// @Override +// protected void configure(HttpSecurity httpSecurity) throws Exception{ +// //调试阶段 +// httpSecurity.csrf().disable().authorizeRequests(); +// httpSecurity.authorizeRequests().anyRequest() +// .permitAll().and().logout().permitAll(); +// } + //用于配置全局的某些通用事物,例如静态资源等 @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers(WHITE_LIST); } +// @Bean +// public PasswordEncoder delegatingPasswordEncoder(){ +// return CustomDelegatingPasswordEncoder.createDelegatingPasswordEncoder(); +// } } + +