当前位置: 首页 > news >正文

使用JWT实现微服务鉴权

目录

一、微服务鉴权

1、思路分析

2、系统微服务签发token

3、网关过滤器验证token

4、测试鉴权功能


前言:

        随着微服务架构的广泛应用,服务间的鉴权与安全通信成为系统设计的核心挑战之一。传统的集中式会话管理在分布式场景下面临性能瓶颈和扩展性不足的问题,而基于令牌的鉴权方案逐渐成为主流。JSON Web Token(JWT)凭借其轻量、无状态、自包含的特性,为微服务间的安全交互提供了高效解决方案。本文将深入探讨JWT的原理、实践及安全策略,结合代码示例解析如何通过JWT实现微服务鉴权,帮助开发者构建高安全性与可维护性的分布式系统。

一、微服务鉴权

1、思路分析

1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录。

2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户。

3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN 。

4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误。

2、系统微服务签发token

        首先需要引入依赖:

<dependency>

  <groupId>io.jsonwebtoken</groupId>

  <artifactId>jjwt</artifactId>

  <version>0.9.0</version>

</dependency>

        然后创建一个JWT的工具类: JwtUtil

/**
 * JWT工具类
 */
public class JwtUtil {
​
    //有效期为
    public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000  一个小时
    //设置秘钥明文
    public static final String JWT_KEY = "itcast";
​
    /**
     * 创建token
     * @param id
     * @param subject
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
​
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        if(ttlMillis==null){
            ttlMillis=JwtUtil.JWT_TTL;
        }
        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);
        SecretKey secretKey = generalKey();
​
        JwtBuilder builder = Jwts.builder()
                .setId(id)              //唯一的ID
                .setSubject(subject)   // 主题  可以是JSON数据
                .setIssuer("admin")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
                .setExpiration(expDate);// 设置过期时间
        return builder.compact();
    }
​
    /**
     * 生成加密后的秘钥 secretKey
     * @return
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
}

        其次在用户成功登录的时候签发token:

 /**
     * 登录
     * @param admin
     * @return
     */
    @PostMapping("/login")
    public Result login(@RequestBody Admin admin){
        boolean login = adminService.login(admin);
        if(login){  //如果验证成功
            Map<String,String> info = new HashMap<>();
            info.put("username",admin.getLoginName());
            String token = JwtUtil.createJWT(UUID.randomUUID().toString(), admin.getLoginName(), null);
            info.put("token",token);
            return new Result(true, StatusCode.OK,"登录成功",info);
        }else{
            return new Result(false,StatusCode.LOGINERROR,"用户名或密码错误");
        }
    }

        使用postman 测试:

3、网关过滤器验证token

        在网关中创建一个过滤器用于校验token,示例代码如下:

/**
 * 鉴权过滤器 验证token
 */
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    private static final String AUTHORIZE_TOKEN = "token";
​
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1. 获取请求
        ServerHttpRequest request = exchange.getRequest();
        //2. 则获取响应
        ServerHttpResponse response = exchange.getResponse();
        //3. 如果是登录请求则放行
        if (request.getURI().getPath().contains("/admin/login")) {
            return chain.filter(exchange);
        }
        //4. 获取请求头
        HttpHeaders headers = request.getHeaders();
        //5. 请求头中获取令牌
        String token = headers.getFirst(AUTHORIZE_TOKEN);
​
        //6. 判断请求头中是否有令牌
        if (StringUtils.isEmpty(token)) {
            //7. 响应中放入返回的状态吗, 没有权限访问
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //8. 返回
            return response.setComplete();
        }
​
        //9. 如果请求头中有令牌则解析令牌
        try {
            JwtUtil.parseJWT(token);
        } catch (Exception e) {
            e.printStackTrace();
            //10. 解析jwt令牌出错, 说明令牌过期或者伪造等不合法情况出现
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //11. 返回
            return response.setComplete();
        }
        //12. 放行
        return chain.filter(exchange);
    }
​
    @Override
    public int getOrder() {
        return 0;
    }
}

4、测试鉴权功能

        如果不携带token直接访问,则返回401错误,示例如下:

        如果携带正确的token,则返回查询结果,示例如下:

        由此可见,我们通过网关使用jwt实现登录的鉴权功能就已经成功实现。

相关文章:

  • HbuilderX如何运行到手机模拟器,安卓模拟器
  • 玩机日记 12 群晖部署AList并配置SSL,安装opkg,使用rclone挂载到本地
  • 使用 OpenTelemetry 和 Langtrace 的 Elastic 分发跟踪基于 RAG 的聊天机器人
  • 【Next.js App Router 深度解剖手册】
  • C++项目:高并发内存池_上
  • Docker构建时,设定默认进入的工作目录的方法
  • 1、FreeRTOS基础知识
  • 用户体验测试
  • unity学习50:NavMeshAgent 区域Areas和cost
  • 鸿蒙NEXT开发-应用数据持久化之关系型数据库
  • cenos 安装 /usr/local/nginx/sbin/nginx这个路径的nginx
  • 微信小程序(uni)+蓝牙连接+Xprint打印机实现打印功能
  • Windows ARM工控主板支持EC200A系列4G模块
  • 向量的点乘的几何意义
  • unity学习45:Animator 的动画层layer
  • SpringBoot整合Redis和Redision锁
  • 多任务(20250210)
  • 计算机网络之TCP的可靠传输
  • 大数据技术之HBase操作归纳
  • uniapp 安卓端 使用axios 和 renderjs 上传 FormData 参数
  • 公司内部网站一般都怎么维护/谷歌aso优化
  • 咸宁网站开发/代运营哪家比较可靠
  • 南川网站制作/b站推广入口
  • 视频在线制作免费生成/宁德seo
  • 工商局网站查询入口/深圳短视频推广
  • 做拼货商城网站/成品网站1688入口网页版