搞了很久终于把配置全部弄完了,从登录验权限,token缓存和验证,到资源白名单验证和openapi 一系列配置到此完成了

注意点:
1、springboot mvc 配置WebMvcConfig  不能继承 WebMvcConfigurationSupport,否则会和Security的映射冲突,如果需要配置,则需要继承接口 WebMvcConfigurer,就不会与他冲突

资源白名单配置

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    private final static String web_file_whiteList = "/web_file_whitelist.properties";
    private Resource resource = new ClassPathResource(web_file_whiteList);

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        Properties props = null;
        try {
            props = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (props != null){
            for(String key : props.stringPropertyNames()){
                String value = (String)props.getProperty(key);
                registry.addResourceHandler(key).addResourceLocations(value);
            }
        }
    }
}

资源地址

spring白名单语法 spring security ip白名单_javascript


web_file_whitelist.propertie 参数


#mvc文件资源访问白名单 key 访问路径path  value 访问目录
/img/**=classpath:/templates/img/
/static/**=classpath:/static/
/templates/**=classpath:/templates/

cors跨域配置

具体根据自己设置,设置header,设置访问路径等

/**
 * @author hmy
 * desc:  cors跨域配置
 * @date 2021/11/8 11:10
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")    // 允许跨域访问的路径
                .allowedOrigins("*")    // 允许跨域访问的源
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")    // 允许请求方法
                .maxAge(168000)    // 预检间隔时间
                .allowedHeaders("*")  // 允许头部设置
                .allowCredentials(true);    // 是否发送cookie
    }

}

SecurityConfig 权限配置类

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserCache;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Properties;

/**
 * @author hmy
 * desc: security权限配置类
 * @date 2021/11/5 16:46
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String whiteFileName = "/security_whitelist.properties";//白名单放行文件
    private static final String whiteDirName ="security_whitelist_dir.properties";//静态资源放行目录
    @Autowired
    private AjaxAuthenticationEntryPoint authenticationEntryPoint;  //  未登陆时返回 JSON 格式的数据给前端(否则为 html)

    @Autowired
    private AjaxAuthenticationSuccessHandler authenticationSuccessHandler;  // 登录成功返回的 JSON 格式数据给前端(否则为 html)

    @Autowired
    private AjaxAuthenticationFailureHandler authenticationFailureHandler;  //  登录失败返回的 JSON 格式数据给前端(否则为 html)

    @Autowired
    private AjaxLogoutSuccessHandler logoutSuccessHandler;  // 注销成功返回的 JSON 格式数据给前端(否则为 登录时的 html)

    @Autowired
    private AjaxAccessDeniedHandler accessDeniedHandler;    // 无权访问返回的 JSON 格式数据给前端(否则为 403 html 页面)

    @Autowired
    private UserDetailsService userDetailsService;//用户详情服务


    //jwt 服务
    @Autowired
    private JwtInfoService jwtInfoService;

    //认证句柄
    @Autowired
    private AuthenticationHandler authenticationHandler;


    @Autowired
    private SecurityWhitelistHandler whitelistHandler;

    @Autowired
    private UserCache userCache;


    /**
     * 权限访问白名单管理
     * @return
     */
    @Bean
    public static Resource securityWhitelistResource() {
        return new ClassPathResource(whiteFileName);
    }

    //配置认证登录
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 使用自定义登录身份认证组件
        auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService, jwtInfoService, authenticationHandler,userCache));
        //这东西千万不能忘
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());

    }



    //http访问接口登录
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭csrf
        //whitelistHandler.handle(http).cors().and().csrf().disable();//关闭csrf每条都必须待token

        //请求权限
//                .authorizeRequests()
//                // 方形白名单
//                .antMatchers("/js/**","/logon","/**/*.html","/apidoc"
//                        ,"/api/file/**","/img/**").permitAll()
//                .authorizeRequests().anyRequest().authenticated();// 其他所有请求需要身份认证


        whitelistHandler.handle(http);

        //资源设置
//        MyRequestCache myRequestCache = new MyRequestCache();
//        myRequestCache.addMatcher("/img/**").addMatcher("/static/**").addEnd();
//        http.setSharedObject(RequestCache.class, myRequestCache);


        //增加数据过滤登陆权限验证
        http.addFilter(new JwtVerifyFilter(super.authenticationManager(), jwtInfoService,
                        new ClassPathResource(whiteFileName)))
                //未登陆返回
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint);
                //注销

        http.logout().logoutSuccessHandler(logoutSuccessHandler);

        //无权限访问
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据

        //用户认证方式 --》自定义认证token方式
        http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);//增加请求数据格式

        http.cors().and().csrf().disable();//关闭csrf每条都必须待token访问
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
         Resource resource = new ClassPathResource(whiteDirName);
        Properties props = null;
        try {
            props = PropertiesLoaderUtils.loadProperties(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (props != null){
            String[] liString = new String[props.values().size()];
            props.values().toArray(liString);
            web.ignoring().antMatchers(liString);
//            web.ignoring().antMatchers("/css/**", "/js/**","/img/**");
        }
        // 设置拦截忽略文件夹,可以对静态资源放行
    }


    /**
     * 登陆权限验证
     * @return
     * @throws Exception
     */
    @Bean
    MyAuthenticationFilter myAuthenticationFilter() throws Exception {
        MyAuthenticationFilter filter = new MyAuthenticationFilter(jwtInfoService);
        //设置要处理的登陆请求的路径
        filter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/api/admin/login", "POST"));

        filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(authenticationFailureHandler);

        filter.setAuthenticationManager(authenticationManagerBean());
        return filter;
    }



}

这里面很多我自己的函数,具体配置按照官方的配置来吧,可以参考配置目录,别自己copy代码,自己思考下