码迷,mamicode.com
首页 > 其他好文 > 详细

JWT实现登录认证实例

时间:2021-02-17 14:45:22      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:this   指定位置   nat   包含   min   实例   log   信息   config   

JWT全称JSON Web Token,是一个紧凑的,自包含的,安全的信息交换协议。JWT有很多方面的应用,例如权限认证,信息交换等。本文将简单介绍JWT登录权限认证的一个实例操作。

JWT组成

JWT由头部(Header),负载(Payload)和签名(Signature)三部分组成。其中头部包含了JWT的声明信息,例如签名所用的算法等。

{
  "alg": "HS256",
  "typ": "JWT"
}

负载部分是负责信息的承载,在通信过程中,我们将要交换的信息放置于负载部分。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

签名部分是JWT安全的保障,在传输过程中,头部和负载部分会经过Base64编码在网络中明文传输,既然是明文,为了保障信息在传输过程中不被篡改。JWT会对编码之后的头部和负载进行一个消息签名。

Signature = HMACSHA256(header + "." + payload + secret)

经过签名之后的JWT保证了数据不会被劫持并篡改。其中secret极为重要,即使有人劫持了消息,在不知道secret的情况下,无法签名出一个有效的JWT。

JWT的形式

JWT由三部分组成:头部,负载和签名。最终的JWT字串可以呈现出这三部分,在JWT中,.为分割各部分的分隔符,按照顺序依次为头部,负载和签名。不过这时你已经看不到JSON的形式,头部和负载会经过Base64编码,最终得到一个字符串。不过Base64并不是加密算法,它是一种编码格式,你可以通过一定的工具解码之后就会得到相应的JSON字串。

技术图片

JWT实现权限认证

在互联网Web应用开发中,最为常见的一项工作就是认证用户,状态化HTTP请求和授予资源访问权限。

其中认证用户通过用户名、密码的登录操作实现,但是HTTP请求是无状态的,为了标记已经登录成功的用户,我们可以通过设置SESSION_IDCOOKIE来标记认证过的请求。但是它们都需要在服务端额外的存储这些SESSION_IDCOOKIE。在最初的单体应用架构中,存储可以在服务端中开辟一块内存,以键值对的形式存储SESSION_ID,COOKIE与用户的映射关系。分布式架构中可以使用REDIS等中间件来实现SESSION共享。

为什要存储映射关系?通过SESSION_IDCOOKIE我们不能够直接得到用户信息吗?其实并不是不可以,而是不安全,SESSION_IDCOOKIE是可以供用户自由操作的。如果直接明文形式的将用户信息写入其中,那么这些信息极有可能会被篡改。所以通常我们会在服务端生成随机字串,写入到SESSION_IDCOOKIE中,再将随机字串与用户之间建立一个映射。这样,客户端的用户并不能随意篡改这些信息了。因为并不知道其他用户的随机字串是什么。

JWT也是字串,只不过是编码之后的字串,而且这个字串是安全的。因为它是被服务端签名认证的。如果有用户修改的痕迹,那么服务端在检验时会发现字串被修改。正是这一特性保障了认证的安全性。

在业务中,JWT可以实现双向校验,即通信双方都可以校验JWT有无被篡改。实现方式是通过非对称加密技术。

Java-JWT权限认证Demo

登陆成功之后,服务端签发JWT代码:

final long expireTime = 1000 * 60 * 60 * 4; //JWT有效期为4小时
final String loginWebToken = JWT.create()
  .withIssuer(configurationProperties.getJwtLoginIssuer())
  .withClaim("username", vo.getUsername()) // 负载部分
  .withClaim("user_id", admin.getId())
  .withExpiresAt(new Date(System.currentTimeMillis() + expireTime)) // 设置有效期
  .sign(Algorithm.HMAC256(configurationProperties.getJwtSignKey())); // 进行签名

签发的JWT可以直接返回给客户端,有客户端JS代码写入下次请求的指定位置,也可以由服务端写入SESSION_IDCOOKIE中。

校验JWT代码,拦截未认证的请求:

try
{
    final String loginWebToken = request.getHeader("Authorization");
    //            final DecodedJWT decodeToken = JWT.decode(loginWebToken);
    //            String username = decodeToken.getClaim("username").asString();
    // JWT验证
    JWT.require(Algorithm.HMAC256(configurationProperties.getJwtSignKey()))
      .withIssuer(configurationProperties.getJwtLoginIssuer())
      .build().verify(loginWebToken);
    return true;
}catch (Exception ex)
{
    Response re = new Response()
      .setMsg("权限受限,请登陆")
      .setData(null)
      .setSuccess(false);
    response.reset();
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json;charset=UTF-8");
    response.getWriter().print(JSON.toJSONString(re));
    return false;
}

业务中使用JWT实现HTTP状态化,服务不同认证用户:

@GetMapping("/user/info")
public Response getUserInfo(HttpServletRequest req)
{
  	final String loginWebToken = request.getHeader("Authorization");
  	final DecodedJWT jwt = JWT.decode(loginWebToken);
  	log.info("欢迎{}使用系统", jwt.getClaim("username");
  	return userService.getUserInfo(jwt.getClaim("user_id"));
}

JWT实现登录认证实例

标签:this   指定位置   nat   包含   min   实例   log   信息   config   

原文地址:https://www.cnblogs.com/Huobn/p/14402344.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!