package com.sandu.common.security.config; import com.sandu.common.security.JwtAccessDeniedHandler; import com.sandu.common.security.JwtAuthenticationEntryPoint; import com.sandu.common.security.TokenFilter; import com.sandu.common.security.annotation.AnonymousAccess; import com.sandu.common.security.token.TokenProvider; import lombok.AllArgsConstructor; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; 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.core.GrantedAuthorityDefaults; 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.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.filter.CorsFilter; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import java.util.HashSet; import java.util.Map; import java.util.Set; /** * 配置类 * * @author chenjiantian */ @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) @EnableWebSecurity @AllArgsConstructor public class SecurityConfig extends WebSecurityConfigurerAdapter { private final TokenProvider tokenProvider; private final CorsFilter corsFilter; private final SecurityProperties properties; private final JwtAuthenticationEntryPoint authenticationErrorHandler; private final JwtAccessDeniedHandler jwtAccessDeniedHandler; private final ApplicationContext applicationContext; @Bean GrantedAuthorityDefaults grantedAuthorityDefaults() { // 去除 ROLE_ 前缀 return new GrantedAuthorityDefaults(""); } @Bean public PasswordEncoder passwordEncoder() { // 密码加密方式 return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { // 搜寻匿名标记 url: @AnonymousAccess Map handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods(); Set anonymousUrls = new HashSet<>(); for (Map.Entry infoEntry : handlerMethodMap.entrySet()) { HandlerMethod handlerMethod = infoEntry.getValue(); AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); if (null != anonymousAccess) { anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); } } httpSecurity // 禁用 CSRF .csrf().disable() .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) // 授权异常 .exceptionHandling() .authenticationEntryPoint(authenticationErrorHandler) .accessDeniedHandler(jwtAccessDeniedHandler) // 防止iframe 造成跨域 .and() .headers() .frameOptions() .disable() // 不创建会话 .and() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .authorizeRequests() // 静态资源等等 .antMatchers( HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/webSocket/**" ).permitAll() // swagger 文档 .antMatchers("/swagger-ui.html").permitAll() .antMatchers("/swagger-resources/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/*/api-docs").permitAll() .antMatchers("/v2/api-docs-ext").permitAll() //.antMatchers("/api/wxmp/**").permitAll() // 文件 .antMatchers("/avatar/**").permitAll() .antMatchers("/file/**").permitAll() // 阿里巴巴 druid .antMatchers("/druid/**").permitAll() // 放行OPTIONS请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 自定义匿名访问所有url放行 : 允许匿名和带权限以及登录用户访问 .antMatchers(anonymousUrls.toArray(new String[0])).permitAll() // 所有请求都需要认证 .anyRequest().authenticated() .and() .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); // .apply(securityConfigurerAdapter()); } @Bean public TokenFilter jwtAuthenticationTokenFilter() { return new TokenFilter(tokenProvider, properties); } }