认证成功后向请求方响应了token信息,那么请求方访问其它系统资源时,就需要带着这个token到后台,后台需要一个授权过滤器获取token信息,并解析用户权限信息,将信息封装到UsernamePasswordAuthentionToken对象存入安全上下文,方便请求时安全过滤处理

这个上下文是以线程为度,一次请求完成后 就结束

package com.itheima.security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.itheima.security.utils.JwtTokenUtil;

import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * ClassName: AuthenticationFilter
 * Package: com.itheima.security.config
 * Description:
 *
 * @Author R
 * @Create 2024/2/12 20:14
 * @Version 1.0
 */
//每次请求 执行一次 不会重复过滤
public class AuthenticationFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.获取http请求头中携带的jwt票据字符串(注意:如果用户尚未认证,则jwt票据字符串不存在)
        String jwtToken = request.getHeader(JwtTokenUtil.TOKEN_HEADER);
        if (StringUtils.isBlank(jwtToken)) {
            //如果票据为空,可能用户准备取认证,所以不做拦截,但是此时UsernamePasswordAuthenticationToken对象未生成,那么即使放行本次请求
            //后续的过滤器链中也会校验认证票据对象
            filterChain.doFilter(request,response);
            return;
        }

        //3.校验票据
        Claims claims = JwtTokenUtil.checkJWT(jwtToken);
        //票据失效
        if (claims==null) {
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            //编码格式
            response.setCharacterEncoding("UTF-8");
            HashMap<String, String> info = new HashMap<>();
            info.put("msg","票据失效");
            info.put("data","");
            info.put("code","1");
            //响应
            response.getWriter().write(new ObjectMapper().writeValueAsString(info));
        }
        //4.从合法的票据中获取用户名和权限信息
        //用户名
        String username = JwtTokenUtil.getUsername(jwtToken);
        //权限信息 [P5, ROLE_ADMIN]
        String roles = JwtTokenUtil.getUserRole(jwtToken);
        //将数组格式的字符串转化成权限对象集合
        String comStr = StringUtils.strip(roles, "[]");
        List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList(comStr);
        //5.组装认证成功的票据对象(认证成功时,密码位置null)
        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, authorityList);
        //6.将认证成功的票据对象保存到安全上下文中,方便后续的过滤器直接获取权限信息
        //以线程为度 当前请求访问结束 那么线程回收 上下文凭证也会回收
        SecurityContextHolder.getContext().setAuthentication(token);
        //7.发行过滤器
        filterChain.doFilter(request,response);
    }
}

配置授权过滤器  过滤一切资源 因为这是资源安全的屏障 所以优先级最高 

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()//定义认证时使用form表单的方式提交数据
                .and()
                .logout()//登出用默认的路径登出 /logout
                .permitAll()//允许所有的用户访问登录或者登出的路径,如果 .anyRequest().authenticated()注释掉,则必须添加permitAll(),否则就不能正常访问登录或者登出的路径
                .and()
                .csrf().disable()
                .authorizeRequests();//授权方法,该方法后有若干子方法进行不同的授权规则处理
        //将自定义的过滤器加入到security过滤器链,且在默认的认证过滤器之前执行
        http.addFilterBefore(myAbstractAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class);
        //配置授权过滤器,过滤一切资源  他是资源安全的屏障 优先级最高 所以要在自定义过滤器之前
        http.addFilterBefore( authenticationFilter(),MyAbstractAuthenticationProcessingFilter.class);
    }

 

spring 自定义类加载器隔离变量_java