用户身份认证

本文探讨了在分布式环境中解决Session共享问题的两种方案:CAS单点登录OAuth2(SOS模式)和Token模式。Token模式因其无状态性和标准化的JSONWebToken(JWT)而被选用。JWT通过头、有效载荷和签名三部分构成,用于验证Token的真实性。在Java项目中,使用jjwt库来创建和验证JWT,并展示了相关工具类的实现。
摘要由CSDN通过智能技术生成

一、用户身份认证

单一服务器:
在这里插入图片描述
对于单一服务器来说:(用户访问有以下5个步骤)
1.用户向服务器发送用户名密码
2.验证服务器后,相关的数据(用户名和用户角色等)将保存在当前的 Session会话中。
3.Web服务器向用户发送Session_id,session信息就会存储在Cookie。
4.之后的用户每个请求都会从Cookie中取出这个Session_id传给服务器。
5.服务器收到Session_id 并对比之前保存的数据,确认用户的身份

存在的问题:
单点性能压力,无法拓展
分布式架构中,需要Session的共享方案,Session共享方案存在技术瓶颈

简单点理解:
有多个Web服务器的时候 每个服务器都会生成自己的Session_id,这样就出现了多次提醒登录的冲突。

解决方案有二种:
一、sos模式(CAS单点登入 OAuth2)
在这里插入图片描述
二、Token模式(项目中使用的是Token模式)
在这里插入图片描述
优点:

  1. Token是无状态的 Session是有状态的
  2. 基于标准化:你的API可以采用标准化的JSON Web Token(JWT)

缺点:
1.占用带宽
2.无法在服务器端销毁

访问令牌的类型有两种:

  • 通明令牌
  • 自包含令牌

JWT令牌

JWT是JSON Web令牌,是一种自包含令牌

JWT的作用:

  • 就是对Token信息的防伪作用 (判断你发来的Token是真假)

JWT的原理

  • 一个JWT是由三部分组成的:JWT的头、有效载荷、签名哈希
  • 最后由三者的组合进行base64编码得到JWT

JWT的用法

  • 客户端接受返回的JWT,将其存储在Cookie中
  • 客户端向服务器端发送请求的时候就会带着JWT,一般存在Cookie中就会自动发送,但是不会跨域,因此一般将它放在http请求的请求头中
  • 当跨域的时候,也可以将它放在POST请求的数据主体中

生成Token的依赖:

<dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.7.0</version>
    </dependency>

工具类

public class JwtUtils {

    private static long tokenExpiration = 24*60*60*1000;
    private static String tokenSignKey = "A1t2g3uigu123456";

    private static Key getKeyInstance(){
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        byte[] bytes = DatatypeConverter.parseBase64Binary(tokenSignKey);
        return new SecretKeySpec(bytes,signatureAlgorithm.getJcaName());
    }

    public static String createToken(Long userId, String userName) {
        String token = Jwts.builder()
                .setSubject("SRB-USER")
                .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
                .claim("userId", userId)
                .claim("userName", userName)
                .signWith(SignatureAlgorithm.HS512, getKeyInstance())
                .compressWith(CompressionCodecs.GZIP)
                .compact();
        return token;
    }

    /**
     * 判断token是否有效
     * @param token
     * @return
     */
    public static boolean checkToken(String token) {
        if(StringUtils.isEmpty(token)) {
            return false;
        }
        try {
            Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    public static Long getUserId(String token) {
        Claims claims = getClaims(token);
        Integer userId = (Integer)claims.get("userId");
        return userId.longValue();
    }

    public static String getUserName(String token) {
        Claims claims = getClaims(token);
        return (String)claims.get("userName");
    }

    public static void removeToken(String token) {
        //jwttoken无需删除,客户端扔掉即可。
    }

    /**
     * 校验token并返回Claims
     * @param token
     * @return
     */
    private static Claims getClaims(String token) {
        if(StringUtils.isEmpty(token)) {
            // LOGIN_AUTH_ERROR(-211, "未登录"),
            throw new BusinessException(ResponseEnum.LOGIN_AUTH_ERROR);
        }
        try {
            Jws<Claims> claimsJws = Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(token);
            Claims claims = claimsJws.getBody();
            return claims;
        } catch (Exception e) {
            throw new BusinessException(ResponseEnum.LOGIN_AUTH_ERROR);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值