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@Configurationpublic class WebApplication {     //过滤器    @Bean    public 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 {    @Override    public void doFilter(final ServletRequest req,                         final ServletResponse res,                         final FilterChain chain) throws IOException, ServletException {        final HttpServletRequest request = (HttpServletRequest) req;        //客户端将token封装在申请头中,格局为(Bearer后加空格):Authorization:Bearer +token        final 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,拿到外面的对象claims            final 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");        }                //加密生成token        return 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;            });        }    };});

运行利用

成果

原文链接:https://blog.csdn.net/change_...

版权申明:本文为CSDN博主「J_小浩子」的原创文章,遵循CC 4.0 BY-SA版权协定,转载请附上原文出处链接及本申明。

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2021最新版)

2.别在再满屏的 if/ else 了,试试策略模式,真香!!

3.卧槽!Java 中的 xx ≠ null 是什么新语法?

4.Spring Boot 2.5 重磅公布,光明模式太炸了!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!