请求时,校验accessToken访问令牌

目的

  1. 校验令牌的有效性,expire是否过期
  2. 令牌的持有者是谁

流程

考虑到前端访问后端api时,都需要进行token验证,可以通过一个过滤器来执行

image.png

项目结构:

image.png

1.新建OAuth2CheckTokenRespDTO类

对应的是图 2.2 返回值 —> 是否有效,userId等等

image.png

2.新增 checkToken方法

在OAuth2Client中新增该方法,校验访问令牌,并返回基本信息 —> 图2.1

image.png

  1. 构建请求头时,将租户id放进去,这里默认是 TENANT_ID = 1,可根据实际情况调整
  2. 将拿到的token放到请求参数中
  3. 执行请求,访问的是 “/check-token” 接口,返回的结果就是 OAuth2AccessTokenRespDTO类

对应的 “/check-token” 接口是 OAuth2OpenController 下的 checkToken :

image.png

3.新建 TokenAuthenticationFilter ,LoginUser 和 SecurityUtils

LoginUser: 登录完之后或者说token校验后会把 LoginUser 创建出来,然后放到线程的上下文里面去,后续如果需要获取userId,可以从上下文中拿到 LoginUser,便可以拿到对应的userId

image.png

新建SecurityUtils:

具体是在TokenAuthenticationFilter中

/**
 * 安全服务工具类
 *
 * @author 芋道源码
 */
public class SecurityUtils {

    public static final String AUTHORIZATION_BEARER = "Bearer";

    private SecurityUtils() {}

    /**
     * 从请求中,获得认证 Token
     *
     * @param request 请求
     * @param header 认证 Token 对应的 Header 名字
     * @return 认证 Token
     */
    public static String obtainAuthorization(HttpServletRequest request, String header) {
        String authorization = request.getHeader(header);
        if (!StringUtils.hasText(authorization)) {
            return null;
        }
        int index = authorization.indexOf(AUTHORIZATION_BEARER + " ");
        if (index == -1) { // 未找到
            return null;
        }
        return authorization.substring(index + 7).trim();
    }

    /**
     * 获得当前认证信息
     *
     * @return 认证信息
     */
    public static Authentication getAuthentication() {
        SecurityContext context = SecurityContextHolder.getContext();
        if (context == null) {
            return null;
        }
        return context.getAuthentication();
    }

    /**
     * 获取当前用户
     *
     * @return 当前用户
     */
    @Nullable
    public static LoginUser getLoginUser() {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return null;
        }
        return authentication.getPrincipal() instanceof LoginUser ? (LoginUser) authentication.getPrincipal() : null;
    }

    /**
     * 获得当前用户的编号,从上下文中
     *
     * @return 用户编号
     */
    @Nullable
    public static Long getLoginUserId() {
        LoginUser loginUser = getLoginUser();
        return loginUser != null ? loginUser.getId() : null;
    }

    /**
     * 设置当前用户
     *
     * @param loginUser 登录用户
     * @param request 请求
     */
    public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
        // 创建 Authentication,并设置到上下文
        Authentication authentication = buildAuthentication(loginUser, request);
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
        // 创建 UsernamePasswordAuthenticationToken 对象
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                loginUser, null, Collections.emptyList());
        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        return authenticationToken;
    }

}

TokenAuthenticationFilter:

image.png

doFilterInternal

  1. 先从 Authorization 请求头中拿到 token
  2. 构建 LoginUser 通过buildLoginUserByToken方法,再通过调用 checkToken的方法最后获取 OAuth2CheckTokenRespDTO,并将里面的值赋给LoginUser
  3. 将LoginUser设置到上下文中
  4. 最好如果你想要获取 LoginUser或者userId,可直接调用 SecurityUtils的 getLoginUSer 和getLoginUserId 方法,即可从上下文或获取

4.将 TokenAuthenticationFilter 添加到 SecurityConfiguration 中

image.png

这样我们就完成了最后配置

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值