JWT实现单点登录(sso)功能

单点登录描述:
单点登录主要时应用在微服务架构中,在任意一个子服务中输入用户的用户名,密码进行登录时,
在跳转到其他系统的时候,就无需在进行登录,直接可以识别出用户的身份,权限以及角色等信息

.
.
JWT:全称java web token, 本质时一组加密后的字符串

JWT有三部分组成: header + payload+ sign (头+载荷+签名)
header记录: jwt使用的加密算法的类型,是一个json字符串,使用base64编码
payload载荷记录: 用户的用户名,用户角色,用户权限,jwt失效时间等循序,使用的时json字符串格式,使用了base64编码
sign签名: 包含了header+payload
JWT中三部分之间使用英文的句号隔开, 也就是 header头.paylouad载荷.sign签名
.
.
.
.
JWT实现单点登录的业务流程:
1,用户通过浏览器发送请求,访问网管,网管中有鉴权过滤器,校验之后,发现用户访问的是认证的微服务,则将请1求放行到认证微服务中
.
.
2,用户在认证微服务的登录页面中, 输入用户名, 密码, 然后登录. 登录后生成jwt字符
串, jwt字符串中有用的用户名, 用户的角色, 用户的权限信息, 返回保存到用户浏览器
cookie中

.
.
*3,用户访问其他服务时,携带token访问,每次访问校验token是否合法有效

JWT实现加密,解密:工具类

public class JwtUtil {

    //有效期为
    public static final Long JWT_TTL = 3600000L;// 60 * 60 *1000  一个小时
    //设置秘钥明文
    public static final String JWT_KEY = "qianfeng";

    /**
     * 创建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();

        /*将上面获取的变量全部设置到指定参数位置进行加密,并通过builder对象中的compact方法返回加密的字符串*/
        JwtBuilder builder = Jwts.builder()
                .setId(id)              //唯一的ID
                .setSubject(subject)   // 主题  可以是JSON数据
                .setIssuer("admin")     // 签发者
                .setIssuedAt(now)      // 签发时间
                .signWith(signatureAlgorithm, secretKey) //使用HS256对称加密算法签名, 第二个参数为秘钥
                .setExpiration(expDate);// 设置过期时间
        return builder.compact();
    }

    /**
     * 解析
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        /*获取秘钥
        * 通过Jwts的parser方法,设置秘钥,设置前端传进来的加密的字符串jwt,底层内部实现对比*/
        SecretKey secretKey = generalKey();
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwt)
                .getBody();
    }

    /**
     * 生成加密后的秘钥 secretKey
     * @return
     */
    public static SecretKey generalKey() {
        /*对秘钥进行base64编码,防止乱码,生成字节数组
        * 用SecretKeySpec对象创建密文(通过有参构造方法:参数1:字节数组,参数2-3:字节的起始和终止位置,参数3:加密的算法名字)*/
        byte[] encodedKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
        return key;
    }
}

认证微服务模块的逻辑判断:


@Component
public class AuthFilter implements Ordered, GlobalFilter {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        /*获取响应对象*/
        ServerHttpRequest request = exchange.getRequest();
        /*从请求中获取用户的url*/
        ServerHttpResponse response = exchange.getResponse();

        /*解析路径*/
        String path = request.getURI().getPath();

        if(StringUtils.isEmpty(path)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();
        }

        /*判断url是否是登录路劲或者是注册路径,是就直接无条件放行*/
        if(path.contains("/auth/login")||path.contains("/auth/regist")){
            /*放行*/
            return chain.filter(exchange);
        }

        /*如果不是,则需要取jwt*/
        MultiValueMap<String, HttpCookie> cookies = request.getCookies();

        if(cookies==null){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();
        }

        /*获取第一个名字叫做token的cookie值*/
        HttpCookie cookie = cookies.getFirst("token");

        if(cookie==null){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();
        }

        /*判断是否能取取到jwt*/
        String  token = cookie.getValue();
        if(StringUtils.isEmpty(token)){
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return  response.setComplete();
        }

        /*如果能取出来,则将解析jwt,然后放行*/
        try {
            Claims claims = JwtUtil.parseJWT(token);
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return   chain.filter(exchange);
    }

注意,这里的放行配合网关实现请求分发到指定微服务上:


server:
  port: 8082
spring:
  application:
    name: gateway
#注册中心
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.200.129:8848
#配置网关(3个微服务模块)
    gateway:
      routes:
        - id: customer
          uri: lb://customer
          predicates:
            - Path=/consumer/**

        - id: provider
          uri: lb://provider
          predicates:
            - Path=/provide/**

        - id: loginserver
          uri: lb://loginserver
          predicates:
            - Path=/auth/**


案例的微服务模块
在这里插入图片描述

  • 2
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
JWT(JSON Web Token)是一种用于在网络应用之间传递声明的开放标准。它可以用于实现单点登录(Single Sign-On,简称 SSO功能,允许用户使用一组凭据(用户名和密码)登录到一个应用程序,并在成功登录后无需再次输入凭据即可访问其他相关应用程序。 实现单点登录功能的步骤如下: 1. 用户登录:当用户在应用程序A中输入凭据进行登录时,应用程序A验证用户的凭据,如果验证成功,则生成一个JWT。 2. JWT生成:JWT包含了用户的相关信息,如用户ID、用户名等,并使用密钥对JWT进行签名。可以使用JWT库来生成和签名JWT。 3. JWT传递:将生成的JWT作为响应返回给客户端,并将其存储在客户端的某个地方,如浏览器的本地存储(LocalStorage)或会话存储(SessionStorage)中。 4. 请求其他应用程序:当用户希望访问其他应用程序B时,客户端将JWT作为请求的一部分发送给应用程序B。 5. JWT验证:应用程序B接收到JWT后,使用相同的密钥进行验证和解码。如果验证成功,应用程序B可以根据JWT中的信息对用户进行认证,允许用户访问相关资源。 以上是JWT实现单点登录功能的基本步骤。需要注意的是,为了保证安全性,JWT的密钥应该被妥善保管,并且在使用时要注意JWT是否过期或被篡改。此外,建议使用HTTPS协议来传输JWT,以确保通信的安全性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值