我是靠谱客的博主 要减肥小蝴蝶,最近开发中收集的这篇文章主要介绍基于 AOP 和 JWT 实现的 Token 身份认证组件,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

基于 AOP 和 JWT 实现的 Token 身份认证组件

    • 原理
    • 服务端使用方式
    • 使用自定义的缓存
    • 客户端使用
    • 测试
    • 源码实现

原理

基于 AOP 面向切面编程,在执行前后插入身份认证的逻辑。

原理细节:

  • 登录过程:这个过程比较简单,将用户 id、用户名、过期时间等属性结合 jwt 工具生成 token,并将用户的信息存入到缓存中,以供后期使用。

  • 验证过程:前端通过 Header 头信息的 Authorization 属性得到 Token,先进行 token 验证,再结合缓存验证,验证成功的话,将用户 id 和用户名等信息存入 ThreadLocal 中,这样在执行切面逻辑的时候。就可以从 ThreadLocal 中获取数据了,如UserManager.getUserId();执行完成后需要清除 ThreadLocal 中的数据;代码如下

class ValidateLoginAspect {

  @Around("pointCutMethod()")
  public Object preHandle(ProceedingJoinPoint pjp) {
    // ......
    UserContextHolder.getInstance().setContext(userMap);
    final Object proceed;
    try {
      proceed = pjp.proceed();
    } finally {
      UserContextHolder.getInstance().clear();
    }
    return proceed;
  }
}
  • 认证接口的范围:给 BaseTokenController这个基类添加 @ValidateLogin
    可以实现一个效果,只要自己的 Controller 继承了BaseTokenController,那么就不用再声明@ValidateLogin注解,自定义Controller中的 mapping 都需要身份认证。
    (PS:这样就免去了繁琐配置:如在拦截器中通过通配符的方式配置哪些接口需要拦截,哪些接口需要放行)

服务端使用方式

添加依赖


<dependency>
    <groupId>com.lyloou</groupId>
    <artifactId>component-security-loginvalidator-starter</artifactId>
    <version>${lyloou.component.version}</version>
</dependency>
  1. 继承BaseTokenController类。 因为这个类被@ValidateLogin标记,所以其下的所有子类都需要身份认证(具体实现细节,查看ValidateLoginAspect)。

@RestController
public class UserController extends BaseTokenController {

    // 从父类继承了ValidateLogin,需要身份验证
    @GetMapping("/ping")
    public String ping() {
        final Integer userId = currentUserId();
        System.out.println(userId);
        return "pong";
    }

}
  1. 如果继承了 BaseTokenController 类,又希望其中的某个方法不要被拦截,可以在方法上标记 @IgnoreValidateLogin

@RestController
public class UserController extends BaseTokenController {

    @Autowired
    TokenService tokenService;

    // 手动忽略身份验证
    @IgnoreValidateLogin
    @GetMapping("/login")
    public String login(String userId, String username) {

        Map<String, String> map = new HashMap<>();
        map.put("userId", userId);
        map.put("userName", username);
        map.put("userAvatar", "http://cdn.lyloou.com/a.jpg");

        final String token = tokenService.createToken(userId, username, JSONUtil.toJsonStr(map));
        return token;
    }
}
  1. 如果没有继承 BaseTokenController,又希望在其中某个方法中做身份认证,获取用户 id,可以在方法上标记@ValidateLogin

@RestController
public class UserController {


    // 手动添加身份验证
    @ValidateLogin
    @GetMapping("userinfo")
    public Map<String, String> userInfo() {
        Map<String, String> map = new HashMap<>();
        map.put(UserManager.X_USER_ID, UserManager.getUserId() + "");
        map.put(UserManager.X_USER_IP, UserManager.getUserIP());
        map.put(UserManager.X_USER_NAME, UserManager.getUserName());
        map.put(UserManager.X_USER_INFO, UserManager.getUserInfo());
        return map;
    }
}

使用自定义的缓存

默认使用了内存缓存ConcurrentHashMap(单机版本的)

也可以自定义缓存

/**
 * @author lilou
 * @since 2021/7/14
 */
@Service
public class RedisCodeCache implements DataCache {

    @Autowired
    private RedisService redisService;
    @Autowired
    private TokenProperties tokenProperties

    @Override
    public void set(String key, String value) {
        set(key, value, tokenProperties.getExpireSecond());
    }

    @Override
    public void set(String key, String value, long timeout) {
        redisService.set(key, value, (int) timeout);
    }

    @Override
    public String get(String key) {
        return redisService.get(key);
    }

    @Override
    public void remove(String key) {
        redisService.del(key);
    }

    @Override
    public boolean containsKey(String key) {
        return redisService.exists(key);
    }
}

客户端使用

在 Header 中配置身份认证 Token 的信息:
如:Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2Mjg4MzQ3MjQsImV4cCI6MTYyOTQzOTUyNCwieC11c2VyLW5hbWUiOiJhYmNkZSIsIngtdXNlci1pZCI6IjEifQ.x0nIhSUPfxC5FlnzJ-MmJvLnJv7w5ZvFzGlNphdSByE

测试

登录接口:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PwizcGCB-1628841233198)(https://raw.githubusercontent.com/lyloou/img/develop/img/20210813155146.png)]

获取用户信息接口:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-azfG97qN-1628841233199)(https://raw.githubusercontent.com/lyloou/img/develop/img/20210813155327.png)]

源码实现

component/component-security-loginvalidator-starter at master · lyloou/component

最后

以上就是要减肥小蝴蝶为你收集整理的基于 AOP 和 JWT 实现的 Token 身份认证组件的全部内容,希望文章能够帮你解决基于 AOP 和 JWT 实现的 Token 身份认证组件所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(39)

评论列表共有 0 条评论

立即
投稿
返回
顶部