点击关注公众号,回复“1024”获取2TB学习资源!

jwt是什么?

JWTs是JSON对象的编码表示。JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值。JWT有助于在clear(例如在URL中)发送这样的信息,可以被信任为不可读(即加密的)、不可修改的(即签名)和URL - safe(即Base64编码的)。

Jwt的组成

  • Header: 标题包含了令牌的元数据,并且在最小包含签名和/或加密算法的类型

  • Claims: Claims包含您想要签署的任何信息

  • JSON Web Signature (JWS): 在header中指定的使用该算法的数字签名和声明

例如:

Header:

{"alg": "HS256","typ": "JWT"
}Claims:{"sub": "1234567890","name": "John Doe","admin": true
}Signature:base64UrlEncode(Header) + "." + base64UrlEncode(Claims),

加密生成的token:

如何保证 JWT 安全

有很多库可以帮助您创建和验证JWT,但是当使用JWT时,仍然可以做一些事情来限制您的安全风险。在您信任JWT中的任何信息之前,请始终验证签名。这应该是给定的。

换句话说,如果您正在传递一个秘密签名密钥到验证签名的方法,并且签名算法被设置为“none”,那么它应该失败验证。

确保签名的秘密签名,用于计算和验证签名。秘密签名密钥只能由发行者和消费者访问,不能在这两方之外访问。

不要在JWT中包含任何敏感数据。这些令牌通常是用来防止操作(未加密)的,因此索赔中的数据可以很容易地解码和读取。

如果您担心重播攻击,包括一个nonce(jti索赔)、过期时间(exp索赔)和创建时间(iat索赔)。这些在JWT规范中定义得很好。

jwt的框架:JJWT

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。

  • JJWT的目标是最容易使用和理解用于在JVM上创建和验证JSON Web令牌(JWTs)的库。

  • JJWT是基于JWT、JWS、JWE、JWK和JWA RFC规范的Java实现。

  • JJWT还添加了一些不属于规范的便利扩展,比如JWT压缩和索赔强制。

规范兼容:
  • 创建和解析明文压缩JWTs

  • 创建、解析和验证所有标准JWS算法的数字签名紧凑JWTs(又称JWSs):

  • HS256: HMAC using SHA-256

  • HS384: HMAC using SHA-384

  • HS512: HMAC using SHA-512

  • RS256: RSASSA-PKCS-v1_5 using SHA-256

  • RS384: RSASSA-PKCS-v1_5 using SHA-384

  • RS512: RSASSA-PKCS-v1_5 using SHA-512

  • PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256

  • PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384

  • PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512

  • ES256: ECDSA using P-256 and SHA-256

  • ES384: ECDSA using P-384 and SHA-384

  • ES512: ECDSA using P-521 and SHA-512

这里以github上的demo演示,理解原理,集成到自己项目中即可。

应用采用 spring boot + angular + jwt

结构图

Maven 引进 : pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nibado.example</groupId><artifactId>jwt-angular-spring</artifactId><version>0.0.2-SNAPSHOT</version><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><commons.io.version>2.4</commons.io.version><jjwt.version>0.6.0</jjwt.version><junit.version>4.12</junit.version><spring.boot.version>1.5.3.RELEASE</spring.boot.version></properties><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring.boot.version}</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>${commons.io.version}</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jjwt.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency></dependencies>
</project>

WebApplication.java

package com.nibado.example.jwtangspr;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@EnableAutoConfiguration
@ComponentScan
@Configuration
public class WebApplication {//过滤器@Beanpublic FilterRegistrationBean jwtFilter() {final FilterRegistrationBean registrationBean = new FilterRegistrationBean();registrationBean.setFilter(new JwtFilter());registrationBean.addUrlPatterns("/api/*");return registrationBean;}public static void main(final String[] args) throws Exception {SpringApplication.run(WebApplication.class, args);}}

JwtFilter.java

package com.nibado.example.jwtangspr;import java.io.IOException;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;import org.springframework.web.filter.GenericFilterBean;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;public class JwtFilter extends GenericFilterBean {@Overridepublic void doFilter(final ServletRequest req,final ServletResponse res,final FilterChain chain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) req;//客户端将token封装在请求头中,格式为(Bearer后加空格):Authorization:Bearer +tokenfinal String authHeader = request.getHeader("Authorization");if (authHeader == null || !authHeader.startsWith("Bearer ")) {throw new ServletException("Missing or invalid Authorization header.");}//去除Bearer 后部分final String token = authHeader.substring(7);try {//解密token,拿到里面的对象claimsfinal Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();//将对象传递给下一个请求request.setAttribute("claims", claims);}catch (final SignatureException e) {throw new ServletException("Invalid token.");}chain.doFilter(req, res);}}

UserController.java

package com.nibado.example.jwtangspr;import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.ServletException;import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;@RestController
@RequestMapping("/user")
public class UserController {//这里模拟数据库private final Map<String, List<String>> userDb = new HashMap<>();@SuppressWarnings("unused")private static class UserLogin {public String name;public String password;}public UserController() {userDb.put("tom", Arrays.asList("user"));userDb.put("wen", Arrays.asList("user", "admin"));}/*以上是模拟数据库,并往数据库插入tom和sally两条记录*/@RequestMapping(value = "login", method = RequestMethod.POST)public LoginResponse login(@RequestBody final UserLogin login)throws ServletException {if (login.name == null || !userDb.containsKey(login.name)) {throw new ServletException("Invalid login");}//加密生成tokenreturn new LoginResponse(Jwts.builder().setSubject(login.name).claim("roles", userDb.get(login.name)).setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256, "secretkey").compact());}@SuppressWarnings("unused")private static class LoginResponse {public String token;public LoginResponse(final String token) {this.token = token;}}
}

ApiController.java

package com.nibado.example.jwtangspr;import io.jsonwebtoken.Claims;import java.util.List;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {@SuppressWarnings("unchecked")@RequestMapping(value = "role/{role}", method = RequestMethod.GET)public Boolean login(@PathVariable final String role,final HttpServletRequest request) throws ServletException {final Claims claims = (Claims) request.getAttribute("claims");return ((List<String>) claims.get("roles")).contains(role);}
}

index.html

<!doctype html>
<html ng-app="myApp">
<head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/><title>JSON Web Token / AngularJS / Spring Boot example</title><meta name="description" content=""><meta name="viewport" content="width=device-width"><link rel="stylesheet" href="libs/bootstrap/css/bootstrap.css"><script src="libs/jquery/jquery.js"></script><script src="libs/bootstrap/js/bootstrap.js"></script><script src="libs/angular/angular.js"></script><script src="app.js"></script>
</head>
<body>
<div class="container" ng-controller='MainCtrl'><h1>{{greeting}}</h1><div ng-show="!loggedIn()">Please log in (tom and sally are valid names)</br><form ng-submit="login()">Username: <input type="text" ng-model="userName"/><span><input type="submit" value="Login"/></form></div><div class="alert alert-danger" role="alert" ng-show="error.data.message"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span><span class="sr-only">Error:</span>{{error.data.message}}</div> <div ng-show="loggedIn()"><div class="row"><div class="col-md-6"><h3><span class="label label-success">Success!</span> Welcome {{userName}}</h3><a href ng-click="logout()">(logout)</a></div><div class="col-md-4"><div class="row header"><div class="col-sm-4">{{userName}} is a</div></div><div class="row"><div class="col-sm-2">User</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleUser"></span></div></div><div class="row"><div class="col-sm-2">Admin</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleAdmin"></span></div></div> <div class="row"><div class="col-sm-2">Foo</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleFoo"></span></div></div>    </div></div></div>
</div>
</body>
</html>

app.js

var appModule = angular.module('myApp', []);appModule.controller('MainCtrl', ['mainService','$scope','$http',function(mainService, $scope, $http) {$scope.greeting = 'Welcome to the JSON Web Token / AngularJR / Spring example!';$scope.token = null;$scope.error = null;$scope.roleUser = false;$scope.roleAdmin = false;$scope.roleFoo = false;$scope.login = function() {$scope.error = null;mainService.login($scope.userName).then(function(token) {$scope.token = token;$http.defaults.headers.common.Authorization = 'Bearer ' + token;$scope.checkRoles();},function(error){$scope.error = error$scope.userName = '';});}$scope.checkRoles = function() {mainService.hasRole('user').then(function(user) {$scope.roleUser = user});mainService.hasRole('admin').then(function(admin) {$scope.roleAdmin = admin});mainService.hasRole('foo').then(function(foo) {$scope.roleFoo = foo});}$scope.logout = function() {$scope.userName = '';$scope.token = null;$http.defaults.headers.common.Authorization = '';}$scope.loggedIn = function() {return $scope.token !== null;}} ]);appModule.service('mainService', function($http) {return {login : function(username) {return $http.post('/user/login', {name: username}).then(function(response) {return response.data.token;});},hasRole : function(role) {return $http.get('/api/role/' + role).then(function(response){console.log(response);return response.data;});}};
});
运行应用

效果

链接:blog.csdn.net/change_on/article/details/76279441

推荐阅读 点击标题可跳转

Win11 被 Linux 社区炮轰!背叛了用户、不要安装

雷军做程序员时写的博客,很强大!

Nginx+keepalived 高可用,防盗链及动静分离配置

一入职,就遇上服务器变矿机!差点滚蛋...

Prometheus+InfluxDB+Grafana 打造高逼格监控平台!

超牛逼的性能监控神器!快速定位线上问题

这款开源工具绝了!!!

SpringBoot + Mybatis-plus + ClickHouse 增删改查教程

面试官:分布式环境下,如何实现 session 共享?

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。

随手在看、转发是最大的支持!

还在直接用 JWT 做鉴权?JJWT 真香相关推荐

  1. 还在直接用JWT做鉴权?JJWT真香

    欢迎关注方志朋的博客,回复"666"获面试宝典 jwt是什么? JWTs是JSON对象的编码表示.JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值.JWT ...

  2. Tornado做鉴权服务性能实践

    一. Torado实现鉴权服务 使用python的第三方jwt做鉴权服务, 生产token代码: def create_token(self, userId, product, level):payl ...

  3. SpringBoot使用security和jwt进行鉴权设计

    一.使用security默认登录接口登录成功.生成token.返回前段 项目的结构如下: 1.引入jar包 <dependency><groupId>org.springfra ...

  4. Spring security+jwt服务鉴权完整代码

    将代码下载到本地, 直接以包的形式添加到项目中就可以实现鉴权功能了. <!-- spring-security 和 jwt start --><dependency><g ...

  5. java 鉴黄_真香,我把百万鉴黄服务源码开源了

    前言 最近某云审查的比较严,图床上的内容也无奈关闭了,有兴趣的小伙伴可以使用炒鸡工具箱自行搭建.今儿跟大家分享一下之前自建鉴黄服务的这个流程顺便分享一下相关源码. 图床架构 鉴黄流程 代码案例 建议有 ...

  6. 50套可视化报表模板直接用,做报告不用愁了!快收藏

    总有人头疼:报表怎么做?数据怎么展现给领导才是最合适的?年终总结怎么让人眼前一亮? 用Excel吧,太低端了,而且是真的丑,万一被pass不就惨了? 用python自动化吧,不会代码,不给自己找事了. ...

  7. 计算机 术语库 excel,Trados直接用Excel做术语库

    术语库都不用制作,您可以直接在Trados中加载Excel术语表作为术语库,不仅操作极其方便,而且极大地简化了术语加载.更新过程.这一切,我们只需要使用完全免费的TermExcelerator插件即可 ...

  8. 还在网上找Demo?这个Java项目真香!

    我前几天专门去网上搜集项目,打算找一些分享给大家用来实践. 但找了一圈发现,网上的项目都比较旧,业务也有些过时,再有就是一些特别大型的项目,不适合初学者做. 不过,我最终还是发现了1个免费的Java训 ...

  9. JWT详解、JJWT使用、token 令牌

    前言 在正式讲解JWT之前,我们先重温一下用户身份认证相关的一些概念: 有状态登录(session认证) 服务器当中记录每一次的登录信息,从而根据客户端发送的数据来判断登录过来的用户是否合法. 缺点: ...

最新文章

  1. 实验四 定位与导航算法
  2. Unity 创建2D平台游戏开发学习教程
  3. html选择想不能为空,jquery – 属性的CSS3选择器,“具有任何值且不为空或空白”...
  4. 监控SRE的黄金信号
  5. PyQt4设置窗口左上角的小图标
  6. 国产数据库年终大盘点!
  7. SA / SAM 题目集
  8. IBM推出全闪存产品 加速服务器I/O性能
  9. 两分钟搞懂,五花八门的门禁卡(ID卡、IC卡、CPU卡),免费复制
  10. 【干货】ArcGIS自动生成拓扑并导出拓扑错误
  11. 【Pr】视频剪辑学习记录——导出
  12. 结巴 python_结巴中文分词使用学习(python)
  13. 集成学习——BAGGING和随机森林
  14. java国际化转换_java 实现国际化 中英文语言切换
  15. day79_babasport第五天
  16. 适合学计算机用的机械键盘,什么机械键盘好用2017 LOL职业玩家用什么键盘好
  17. 全连接网络和卷积神经网络
  18. 【数据库】多表查询二----嵌套查询(子查询)
  19. Linux如何复制文件和文件夹到另一个目录
  20. Unity实战之牧师与魔鬼(动作分离版)

热门文章

  1. php 微信自定义分享,微信自定义分享(php方法)
  2. 阿里云盘的目录文件列表程序Alist
  3. 2021年4月Bmob无法访问Bmob云服务器
  4. 关于近视眼手术网友的评价
  5. 这样的成品app直播源码到手一定会后悔
  6. 如何把自己的百度网盘的内容分享给别人
  7. 2014Esri中国用户大会亮点系列之——典型案例与应用阐释新一代WebGIS
  8. 【转载】SMPS开关电源有两种HFS(高频)和FTS(瞬响)
  9. 对话印奇:我们所坚持的不会改变,旷视跳出企业科研“周期律”
  10. 【SpringCloud】设置接口同时支持返回多种数据类型(json、xml)