Spring Security 安全认证框架

一、认证流程 

基本原理

  • UsernamePasswordAuthenticationFilter过滤器用于处理基于表单方式的登录验证,该过滤器默认只有当请求方法为post、请求页面为/login时过滤器才生效,如果想修改默认拦截url,只需在刚才介绍的Spring Security配置类WebSecurityConfig中配置该过滤器的拦截url:.loginProcessingUrl("url")即可;
  • BasicAuthenticationFilter用于处理基于HTTP Basic方式的登录验证,当通过HTTP Basic方式登录时,默认会发送post请求/login,并且在请求头携带Authorization:Basic dXNlcjoxOWEyYWIzOC1kMjBiLTQ0MTQtOTNlOC03OThkNjc2ZTZlZDM=信息,该信息是登录用户名、密码加密后的信息,然后由BasicAuthenticationFilter过滤器解析后,构建UsernamePasswordAuthenticationFilter过滤器进行认证;如果请求头没有Authorization信息,BasicAuthenticationFilter过滤器则直接放行;
  • FilterSecurityInterceptor的拦截器,用于判断当前请求身份认证是否成功,是否有相应的权限,当身份认证失败或者权限不足的时候便会抛出相应的异常;
  • ExceptionTranslateFilter捕获并处理,所以我们在ExceptionTranslateFilter过滤器用于处理了FilterSecurityInterceptor抛出的异常并进行处理,比如需要身份认证时将请求重定向到相应的认证页面,当认证失败或者权限不足时返回相应的提示信息;

二、两种过滤

静态资源过滤

@Override

public void configure(WebSecurity web) throws Exception {

web.ignoring().antMatchers("/css/**", "/js/**", "/index.html", "/img/**", "/fonts/**", "/favicon.ico", "/verifyCode");

}

接口过滤

.antMatchers("/sys_bookmark/**","/sys_code/**","/sys_user/**","/sys_api/**").permitAll()

接口过滤这一块还需要自定义一次过滤器 继承 BasicAuthenticationFilter 的类要放行接口

   @Override
    protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws IOException, ServletException {
        String tokenHeader = request.getHeader(JwtTokenUtil.TOKEN_HEADER);

        System.out.println("获取头部数据 >>>> " + tokenHeader);

        // 获取请求路径
        String requstUrl = request.getRequestURI();

        log.info("获取路径 >>> " + requstUrl);

        String url1 = ".*/sys_code/.*";
        String url2 = ".*/sys_bookmark/.*";
        String url3 = ".*/sys_user/.*";
        String url4 = ".*/sys_api/.*";

        if (Pattern.matches(url1, requstUrl)) {
            log.info("获取路径1");
            chain.doFilter(request, response);
            return;
        } else if (Pattern.matches(url2, requstUrl)) {
            log.info("获取路径2");
            chain.doFilter(request, response);
            return;
        } else if (Pattern.matches(url3, requstUrl)) {
            log.info("获取路径3");
            chain.doFilter(request, response);
            return;
        }else if (Pattern.matches(url4,requstUrl)) {
            log.info("获取路径4");
            chain.doFilter(request, response);
            return;
        }

        // 若请求头中没有Authorization信息 或是Authorization不以Bearer开头 则直接放行
        if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtil.TOKEN_PREFIX)) {
            log.info("请求未通过");
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            Map<String,Object> map = new HashMap<>();
            map.put("code",2003);
            map.put("message","您未登录请先登录");
            writer.write(JSON.toJSONString(map));
            return;
        }


        // 去掉前缀 获取Token字符串
        String token = tokenHeader.replace(JwtTokenUtil.TOKEN_PREFIX, "");
        // 校验token有效时间
        if (JwtTokenUtil.isExpiration(token)){
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter writer = response.getWriter();
            Map<String,Object> map = new HashMap<>();
            map.put("code",3000);
            map.put("message","token已失效");
            writer.write(JSON.toJSONString(map));
            return;
        }

        // 若请求头中有token 则调用下面的方法进行解析 并设置认证信息
        SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
        super.doFilterInternal(request, response, chain);
    }

猜你喜欢

转载自blog.csdn.net/qq_35930739/article/details/124866246