1. 一个JWT实际上就是一个字符串,由三部分组成 头部,载荷,签名
头部:事描述类型,签名,算法等 可以被表示成一个JSON对象
载荷:存放有效信息的地方 包含三个部分
(1)标准注册中的声明-建议但不强制使用
  iss:jwt签发者
  sub:jwt所面向的用户
  aud:接收jwt的一方
  exp:jwt的过期时间,时间必须大于签发时间
  nbf:定义在什么时间以前,这个jwt都是不可用的
  iat:jwt的签发时间
  jti:jwt的唯一身份标识,用来作为token
(2)公共的声明
  一般是公司相关的信息,由于这部分可以被解密,所以不要添加敏感信息
(3)私有的声明
  可以被解密,,
  可以自定义claim
  载荷的例子 {"sub":"1233","name":"John","admin":true}
签证:三部分
  header(base64后的)
  payload(base64后的)
  secret
2. 名词解释 Base64
  64个可打印二进制数据 2^6为64 每6个比特是一个单元,打印一个字符,3个字节有24个比特
  对应4个Base64 JDK中提供了BASE64Encoder BASE64Decoder 编码,解码
3. java的jjwt
  JJWT是一个提供端到端的JWT创建和验证的Java库
4. 使用

(一)引入依赖

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

(二)测试使用

package BigTest.jwt;

import com.JwtBootApplication;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import java.text.SimpleDateFormat;
import java.util.Date;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JwtBootApplication.class)
public class CreateJwtTest {
/*
* java.lang.IllegalArgumentException:
* secret key byte array cannot be null or empty.
* 是因为secret太简单了 没有加时间
* */
@Test
public void testJwt(){
JwtBuilder jwtBuilder = Jwts.builder().setId("888")
.setSubject("小白")
.setIssuedAt(new Date()) //setIssuedAt用于设置签发时间
.signWith(SignatureAlgorithm.HS256, "onetwothree"); //signWith用于设置签名秘钥
System.out.println(jwtBuilder.compact());
//eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NzMyOTAwOTh9.-lqlLqmAG2qQ15Ge7IlcgIAgj0V54L0GCA5dJfM6Lw4 }
@Test
public void ParseJwtTest(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NzMyOTAwOTh9.-lqlLqmAG2qQ15Ge7IlcgIAgj0V54L0GCA5dJfM6Lw4";
Claims claims = Jwts.parser().setSigningKey("onetwothree").parseClaimsJws(token).getBody(); System.out.println("id="+claims.getId());
System.out.println("subject="+claims.getSubject());
System.out.println("IssueAt="+claims.getIssuedAt());
} /**
* 带过期时间的jwt-token
* ExpiredJwtException: token过期报错
*/
@Test
public void testJwt_time(){
long now = System.currentTimeMillis();
long exp = now + 1000*60;//设置时间为1分钟
JwtBuilder jwtBuilder = Jwts.builder().setId("888")
.setSubject("小白")
.setIssuedAt(new Date()) //setIssuedAt用于设置签发时间
.setExpiration(new Date(exp))//setExpiration设置token过期时间
.signWith(SignatureAlgorithm.HS256, "onetwothree"); //signWith用于设置签名秘钥
System.out.println(jwtBuilder.compact()); }
@Test
public void ParseJwtTest_time(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NzMyOTg0MDUsImV4cCI6MTU3MzI5ODQ2NX0.Rx-0BrJ2032aUz_vrttXw-9_idfQe3LHzCnLOWpsaqs";
Claims claims = Jwts.parser().setSigningKey("onetwothree").parseClaimsJws(token).getBody();
System.out.println("id="+claims.getId());
System.out.println("subject="+claims.getSubject());
System.out.println("IssueAt="+claims.getIssuedAt());
SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
System.out.println("当前时间:"+sdf.format(new Date()) );
}
/*
* 自定义claims,上面的只存储了id和subject 自定义可以存储自己向存储的内容
* */
@Test
public void testJwt_claims(){
long now = System.currentTimeMillis();
long exp = now + 1000*60; //设置过期时间为1分钟
JwtBuilder claim = Jwts.builder().setId("9768")
.setSubject("zhangsan")
.setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS256,"onetwothree")
.setExpiration(new Date(exp))
.claim("roles", "admin")
.claim("address", "beijing");
System.out.println(claim.compact());
}
@Test
public void ParseJwtTest_claim(){
String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5NzY4Iiwic3ViIjoiemhhbmdzYW4iLCJpYXQiOjE1NzMzMDg0ODUsImV4cCI6MTU3MzMwODU0NSwicm9sZXMiOiJhZG1pbiIsImFkZHJlc3MiOiJiZWlqaW5nIn0.Y-8hZIAlWzegSadQWSQGRc9gUBGlBznRT984jtqQZ-s";
Claims claims = Jwts.parser().setSigningKey("onetwothree").parseClaimsJws(token).getBody(); System.out.println("id:"+claims.getId());
System.out.println("subject:"+claims.getSubject());
System.out.println("roles:"+claims.get("roles"));
System.out.println("logo:"+claims.get("address"));
SimpleDateFormat sdf=new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
System.out.println("签发时间:"+sdf.format(claims.getIssuedAt()));
System.out.println("过期时间:"+sdf.format(claims.getExpiration()));
System.out.println("当前时间:"+sdf.format(new Date()) ); } }

(三)在springboot中的使用

在application.yml添加配置

jwt:
config:
key: zhedoumeishenme
ttl: 360000

 编写utils

package com.xxy.server.common.utils;

import io.jsonwebtoken.*;
import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.Date; @ConfigurationProperties("jwt.config")//拿到 .yml中的参数
public class JwtUtils {
private String key;
private long ttl; //一个小时 public String getKey() {
return key;
} public void setKey(String key) {
this.key = key;
} public long getTtl() {
return ttl;
} public void setTtl(long ttl) {
this.ttl = ttl;
} /**
* 生成jwt
* @param id
* @param subject
* @param roles
* @return
*/
public String createJWT(String id, String subject, String roles){
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder().setId(id)
.setSubject(subject)
.signWith(SignatureAlgorithm.HS256, key)
.setIssuedAt(now)
.claim("roles", roles);
if(ttl > 0){
builder.setExpiration(new Date(nowMillis+ttl));
} return builder.compact();
} /**
* 解析JWT
* @param jwtStr
* @return
*/
public Claims parseJWT(String jwtStr){
return Jwts.parser()
.setSigningKey(key)
.parseClaimsJws(jwtStr)
.getBody();
}
}
Jwt请求拦截器
package com.xxy.server.common.interceptors;

import com.xxy.server.common.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @Description: Jwt请求拦截器
* @Author: xuxiaoyu
* @Create: 2019-11-10 20:45
*/
@Component
public class JwtFilter extends HandlerInterceptorAdapter {
@Autowired
private JwtUtils jwtUtils; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("经过了jwtfilter拦截器");
final String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) {
Claims claims = jwtUtils.parseJWT(authHeader);
if(claims != null){
if("admin".equals(claims.get("roles"))){
request.setAttribute("admin_claims", claims);
}
if("user".equals(claims.get("roles"))){
request.setAttribute("user_claims", claims);
}
}
}
return true;
}
}

配置到mvc中

package com.xxy.server.common.config;

import com.xxy.server.common.interceptors.JwtFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; /**
* description:该类可以来扩展Spirng MVC的功能
*/
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
@Autowired
private JwtFilter jwtFilter;
/**
* description:添加默认视图映射,当访问localhost:8080/时,跳转到index.html页面
* params : registry
* @return void
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index"); }
/**
* description: Jwt请求拦截器,任何请求都会经过这个拦截器
* @param registry
*/
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(jwtFilter)
.addPathPatterns("/**")
.excludePathPatterns("/login","/captcha");
}
}

然后在方法中就可以判断使用了

 Claims claims = (Claims) request.getAttribute("admin_claims");
if (claims == null) {
return HttpResultUtil.error("权限不足");
}

基于JWT的token认证机制的更多相关文章

  1. 基于JWT的Token认证机制及安全问题

    [干货分享]基于JWT的Token认证机制及安全问题 https://bbs.huaweicloud.com/blogs/06607ea7b53211e7b8317ca23e93a891

  2. iOS 开发之基于JWT的Token认证机制及解析

    在移动端和服务端通信中,一般有两种认证方式:token 和 session. 1.session/cookie 认证机制: 在服务端创建一个Session对象,同时在客户端的浏览器端创建一个Cooki ...

  3. token 与 基于JWT的Token认证

    支持跨域访问,无状态认证 token特点 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输 无状态(也称:服务端可扩展行): ...

  4. 简单说说基于JWT的token认证方式

    一.什么是认证 好多人不知道什么是认证,认证,其实就是服务端确认用户身份.Http协议是无状态的,客户端发送一条请求,服务端返回一条响应,二者就算做成一单买卖,一拍两散.在很久以前,互联网所能提供的服 ...

  5. ASP.NET WebApi 基于JWT实现Token签名认证

    一.前言 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebServi ...

  6. ASP.NET Web API 2系列(四):基于JWT的token身份认证方案

    1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...

  7. 基于jwt的token验证

    一.什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). 该token被设计为紧凑且安全的,特别适用于分布 ...

  8. 基于JWT的Token身份验证

    ​ 身份验证,是指通过一定的手段,完成对用户身份的确认.为了及时的识别发送请求的用户身份,我们调研了常见的几种认证方式,cookie.session和token. 1.Cookie ​ cookie是 ...

  9. 基于JWT的Token开发案例

    代码地址如下:http://www.demodashi.com/demo/12531.html 0.准备工作 0-1运行环境 jdk1.8 maven 一个能支持以上两者的代码编辑器,作者使用的是ID ...

随机推荐

  1. Mysql: if 结构

    if结构 语法 if  条件1  then  语句1; elseif   条件2   then  语句2; ... else 语句n;   # 可以不写 应用场合:应用在begin end 中 SEL ...

  2. Power Tower

    题目大意:给出一段长为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\) ,一个模数 \(m\) .每次询问给定 \(l,r\) 求 \(a_l^{{a_{l+1}^\cdots}^{ ...

  3. VM虚拟机安装 常用Linux命令 网卡配置 (第二天)

    VM虚拟机安装:(昨天已经安装好了VM了,按照提示安装就好,很简单) 1.安装centos7虚拟机,现在磁盘里面新建文件夹作为安装文件夹 2.找到centos7的iso文件,打开vm-新建虚拟机-按照 ...

  4. grep -q

    grep -q用于if逻辑判断      安静模式,不打印任何标准输出.如果有匹配的内容则立即返回状态值0. grep -q的用法 #  if  grep -q hello a.txt ; then ...

  5. 如何拖拽DIV边线并左右自适应改变大小?

    //树图拉伸    jQuery(function ($){                  var doc = $(document), dl = $(".side-tree" ...

  6. JDBC批处理方法

    每次新建Connection的时候相当于建了一座桥,每次一辆车(PreparedStatement)运送货物(ResultSet)成本太高! 每次都建立网络连接的时间远远大于本地的时间,为了处理大量的 ...

  7. web应用中并发控制的实现,各种锁的集合

    参考:http://blog.csdn.net/xiangwanpeng/article/details/55106732 B/S构架的应用越来越普及,但由于它有别于C/S构架的特殊性,并发控制始终没 ...

  8. Codeforces 446C 线段树 递推Fibonacci公式

    聪哥推荐的题目 区间修改和区间查询,但是此题新颖之处就在于他的区间修改不是个定值,而是从L 到 R 分别加 F1.F2....Fr-l+1 (F为斐波那契数列) 想了一下之后,觉得用fib的前缀和来解 ...

  9. c# 属性 (get、set)

    //属性是一种用于访问对象或类的特性的成员.属性可以包括字符串的长度.字体的大小.窗体的标题和客户的名称.属性是成员的自然扩展,二者都是关联类型的命名成员.namespace ConsoleAppli ...

  10. zuul网关配置

    静态路由:通过url匹配映射地址进行静态路由(只会把到达zuul网关的请求按照发送,并把匹配请求地址 /common-service/ ->http://localhost:9001/) zuu ...