javajwt(javajwt与jwk)

本篇文章给大家谈谈javajwt,以及javajwt与jwk对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Spring Security 整合 JSON Web Token(JWT)

注:参考 Spring Security 整合 JSON Web Token(JWT) 提升 REST 安全性 ,写的特别全面,本文只是学习总结

基于token的鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要搜返吵去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

流程上是这样的:

1.用户使用用户名密码来请求服务器

2.服务器进行验证用户的信息

3.服务器通过验证发送给用户一个token

4.客户端存储token,并在每次请求时附送上这个token值

5.服务端验证token值,并返回数据

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了世侍Access-Control-Allow-Origin: *。

第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).

jwt的头部承载两部分信息:

声明类型,这里是jwt

声明加密的算法 通常直接使用 HMAC SHA256

完整的头世敏部就像下面这样的JSON:

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分.

载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分

1.标准中注册的声明

2.公共的声明

3.私有的声明

标准中注册的声明 (建议但不强制使用) :

iss : jwt签发者

sub : jwt所面向的用户

aud : 接收jwt的一方

exp : jwt的过期时间,这个过期时间必须要大于签发时间

nbf : 定义在什么时间之前,该jwt都是不可用的.

iat : jwt的签发时间

jti : jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

公共的声明 :

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明 :

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

定义一个payload:

然后将其进行base64加密,得到Jwt的第二部分。

jwt的第三部分是一个签证信息,这个签证信息由三部分组成:

1.header (base64后的)

2.payload (base64后的)

3.secret

这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。

将这三部分用.连接成一个完整的字符串,构成了最终的jwt:

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

如何应用

一般是在请求头里加入Authorization,并加上Bearer标注:

服务端会验证token,如果验证通过就会返回相应的资源。整个流程就是这样的:

jwt-diagram

总结

优点

因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。

因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。

便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。

它不需要在服务端保存会话信息, 所以它易于应用的扩展

安全相关

不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。

保护好secret私钥,该私钥非常重要。

如果可以,请使用https协议

在SpringBoot中整合JWTSpring Security的步奏:

1.在项目中引入(本项目使用Gradle)

2.配置

目录结构如下:

WebSecurityConfig文件:

java jwt如何刷新过期时间

客户端

auth_header = JWT.encode({ user_id: 123, iat: Time.now.to_i, # 指定token发布时间 exp: Time.now.to_i + 2 # 指定token过期时间为2秒后,2秒时间足够一次HTTP请求,同时在一定程度确保上一次token过期,减少replay attack的概率运吵;}, "my shared secret")

RestClient.get("", authorization: auth_header)

服务端

class ApiController ActionController::Base

attr_reader :current_user

before_action :set_current_user_from_jwt_token

def set_current_user_from_jwt_token

# Step 1:解码JWT,并获取User ID,这个时候不对Token签名进行检查

# the signature. Note JWT tokens are *not* encrypted, but signed.

payload = JWT.decode(request.authorization, nil, false) # Step 2: 检查该用户是否存在于数据库

@current_user = User.find(payload['user_id'])

# Step 3: 检查Token签名是否正确.

JWT.decode(request.authorization, current_user.api_secret)

# Step 4: 检查握首 "iat" 和"exp" 以确保这个Token是在2秒旁皮侍内创建的.

now = Time.now.to_i if payload['iat'] now || payload['exp'] now # 如果过期则返回401

end

rescue JWT::DecodeError

# 返回 401

endend

[img]

SpringBoot整合JWT实现登录认证

1、JWT的构成

- 头部(header):描述该JWT的最基本的信息,如类型以及签名所用的算法。

- 负载(payload):存放有效信息的地方。

- 签证(signature):base64加密后闹枝的header、base64加密后的payload和密钥secret加密后组成。

2、整合JWT

2.1 引入JWT依赖

com.auth0

java-jwt

3.18.3

2.2 编写漏好JWTUtils工具类

package com.stock.utils;

import com.auth0.jwt.JWT;

import com.auth0.jwt.JWTCreator;

import com.auth0.jwt.JWTVerifier;

import com.auth0.jwt.algorithms.Algorithm;

import com.auth0.jwt.interfaces.DecodedJWT;

import com.auth0.jwt.interfaces.Verification;

import java.util.Calendar;

import java.util.Map;

public class JWTUtils {

private static final String SING="@#$%^*";

// 生成token

public static String getToken(Map map){

Calendar instance = Calendar.getInstance();

instance.add(Calendar.MINUTE,30);

//创建jwt builder

JWTCreator.Builder builder = JWT.create();

//payload

builder.withExpiresAt(instance.getTime());

map.forEach((k,v)-{

builder.withClaim(k,v);

});

//设置签名

String token = builder.sign(Algorithm.HMAC256(SING));

return token;

}

//验证令牌

public static void verifyToken(String token){

JWTVerifier require = JWT.require(Algorithm.HMAC256(SING)).build();

require.verify(token);

}

//获取token信息

public static DecodedJWT getTokenInfo(String token){

DecodedJWT verify = JWT.require(Algorithm.HMAC256(SING)).build().verify(token);

return verify;

}

}

2.3 编写拦截液搜敏器

public class JWTInterceptor implements HandlerInterceptor {

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {

System.out.println("OPTIONS请求,放行");

return true;

}

HashMap map = new HashMap();

String token = request.getHeader("token");

try {

JWTUtils.verifyToken(token);

return true;

}catch (SignatureVerificationException e){

map.put("msg","无效签名!");

}catch (TokenExpiredException e){

map.put("msg","token过期!");

}catch (AlgorithmMismatchException e){

map.put("msg","token加密算法不一致");

}catch (Exception e){

map.put("msg","无效签名!");

}

map.put("state",404);

map.put("path","/login");

//将map转化为字符串返回给前端

String result = new ObjectMapper().writeValueAsString(map);

response.setContentType("application/json;charset=UTF-8");

response.getWriter().println(result);

return false;

}

}

注意:

1、token存放在请求的header中;

2、在前后端分离的项目中,发送的GET/POST请求实则为两次请求。第一次请求为OPTIONS请求,第二次请求才是GET/POST请求;在OPTIONS请求中,不会携带请求头的参数,会导致在拦截器上获取请求头为空,自定义的拦截器拦截成功。第一次请求不能通过,就不能获取第二次的请求。所以需要在拦截器中加上如下代码来判断是否为OPTIONS请求,对于OPTIONS请求直接放过。

if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) {

System.out.println("OPTIONS请求,放行");

return true;

}

2.4 配置拦截器

package com.stock.config;

import com.stock.Interceptors.JWTInterceptor;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration

public class IntercepterConfg implements WebMvcConfigurer {

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(new JWTInterceptor())

.addPathPatterns("/**")

.excludePathPatterns("/login");

}

}

2.5 编写Controller

package com.stock.controller;

import com.stock.entity.User;

import com.stock.result.Result;

import com.stock.service.UserService;

import com.stock.utils.JWTUtils;

import com.stock.utils.ResultUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RequestBody;

import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController

public class LoginController {

private UserService userService;

@Autowired

public LoginController(UserService userService) {

this.userService = userService;

}

@PostMapping("/login")

public Result register(User user){

HashMap map = new HashMap();

map.put("username",user.getUserName());

String token = JWTUtils.getToken(map);

HashMap data = new HashMap();

data.put("token",token);

return ResultUtils.getresult(200,"登录成功!",data);

}

@GetMapping("/main")

public Result tomain(){

return ResultUtils.getresult(200,"访问成功",null);

}

}

2.6使用Postman测试

- 未登录前访问127.0.0.1:8888/main

- 先登录再访问127.0.0.1:8888/main

jwt与token+redis,哪种方案更好用?

1.问题描述

jwt与token+redis,哪种方案更好用?

问题结论

刚好最近有项目使用了jwt,而且是定制化的jwt的认证机制,就个人的理解而言,各自有其优缺点,并且针对不同的场景需要进行约束性开发,如用户剔除、同一用户每2h只生成一次jwt等。

2.Token机制简述

2.1Token的用途

用户在登录APP时,APP端会发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果验证成功,就会生成相应位数的字符产作为token存储到服务器中,并且磨隐将该token返回给APP端。以后APP再次请求时,凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让用户重新登录。其中,服务器上会给token设置一个有效期,每次APP请求的时候都验证token和有效期。

在存储的时候把token进行对称加密存储,用到的时候再解密。文章最开始提到的签名sign:将请求URL、时间戳、token三者合并,通过算法进行加密处理。

2.2token+redis机制

用户验证通过后,服务端通过如uuid相关的方法,生成token,存储用户信息。当请求服务时,客户端将token带上激含来,进行查询验证,如token存在并在有限期内,请求有效,否则请求非法。

token+redis机制是中心化的,每次验证token有效性时,都需要访问redis,其核心优点实服务端可以主动让token失效,缺点是每次都要进行redis查询。占用redis存储空间。

2.3jwt机制

这是一种无状态身份验证机制,因为用户状态永远不会保存在服务器内存中。服务器受保护的路由将在授权头中检查有效的JWT,如果存在,则允许用户访问受保护的资源。由于JWT是独立的,所有必要的信息都在那里,减少了多次查询数据库的需求。

Javajwt普遍选用java-jwt工具包依赖,gradle依赖:compile'com.auth0:java-jwt:3.2.0'用户发起登录请求,验证通过后,服务端创建一个加密后的JWT信息,作为Token返回。在后续请求中JWT信息作为请求头,发给服务端。服务端拿到JWT之后进行解密,正确解密表示此次请求合法,验证通过;解密失败说明Token无效或者已过期。

jwt的有点主要有:a.其是去中心化的,便于分布式系统使用;2.基本信息可以直接放在token中。user_id,session_id;3.功能权限信息可以直接放在token中。用bit位表示用户所具有的功能权限。其缺点有:服务端无法主动让token失效,另一个是无法很好的控制payload的数据量。

3.小结

jwt和token+redis两种方案,没有最优,只有结合不同的业务场景,需求最适合的方案。就比如token2h过期,同一用户每1.5h只生成瞎铅厅一次token,当两次token并存时,同时有效。大家可以考虑在这两种方案的前提下,分别如何实现?

java jwt token 生成很慢啊

jwt不算慢,基本是毫秒,你测试的方法估计有问题,单元测试1次jwt生成基本都是1~2秒,因为java程序刚刚启动占用大量资源,你循环1000次jwt生成速颤李兄度对比就知道了, 基本茄袭是毫秒级扰含别!

关于javajwt和javajwt与jwk的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签列表