package com.common.security.configure; import com.common.annotation.NoToken; import com.common.core.utils.SpringContextUtils; import com.common.filter.CorsFilter; import com.common.filter.JwtAuthenticationTokenFilter; import com.deloitte.system.model.AppConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDecisionVoter; import org.springframework.security.access.vote.AuthenticatedVoter; import org.springframework.security.access.vote.UnanimousBased; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.core.userdetails.UserDetailsService; import org.springframework.security.web.access.expression.WebExpressionVoter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.*; import java.util.stream.Collectors; /** * @author 廖振钦 * @date 2022-01-14 */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private RestfulAccessDeniedHandler restfulAccessDeniedHandler; @Autowired private RestAuthenticationEntryPoint restAuthenticationEntryPoint; // 放行所有请求 @Override protected void configure(HttpSecurity httpSecurity) throws Exception { Map handlerMethods = ((RequestMappingHandlerMapping)SpringContextUtils.getBean("requestMappingHandlerMapping")).getHandlerMethods(); Set anonymousUrls = new HashSet<>(); for (Map.Entry infoEntry : handlerMethods.entrySet()) { // 获取所有接口的方法 HandlerMethod handlerMethod = infoEntry.getValue(); if (handlerMethod.hasMethodAnnotation(NoToken.class)) { PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition(); Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new); anonymousUrls.addAll(requestCondition.getPatterns().stream().map(m -> m).collect(Collectors.toList())); } } anonymousUrls.add("/druid/**"); httpSecurity.csrf() .disable() .sessionManagement()// 基于token,所以不需要session .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() .antMatchers(HttpMethod.GET, // 允许对于网站静态资源的无授权访问 "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/swagger-resources/**", "/v2/api-docs/**", "/druid/**" ) .permitAll() .antMatchers(anonymousUrls.toArray(new String[0])) .anonymous() .anyRequest()// 除上面外的所有请求全部需要鉴权认证 .authenticated() // 自定义accessDecisionManager .accessDecisionManager(accessDecisionManager()); ;//放行option请求 // 禁用缓存 httpSecurity.headers().cacheControl(); // 添加JWT filter httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); // 添加跨域 filter httpSecurity.addFilterBefore(corsFilter(), JwtAuthenticationTokenFilter.class); //添加自定义未授权和未登录结果返回 httpSecurity.exceptionHandling() .accessDeniedHandler(restfulAccessDeniedHandler) .authenticationEntryPoint(restAuthenticationEntryPoint); } @Bean public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { return new JwtAuthenticationTokenFilter(); } @Bean public CorsFilter corsFilter() { return new CorsFilter(); } @Bean public UserDetailsService userDetailsService() { //获取登录用户信息 return username -> { AppConfig appConfig = AppConfig.dao.findByAppid(username); return new AppDetails(appConfig); }; } @Bean public AccessDecisionManager accessDecisionManager() { List> decisionVoters = Arrays.asList( new WebExpressionVoter(), // new RoleVoter(), new RoleBasedVoter(), new AuthenticatedVoter()); return new UnanimousBased(decisionVoters); } }