0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何才能保证JWT安全

Android编程精选 来源:CSDN博客 作者:J_小浩子 2021-09-29 15:09 次阅读

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;

});

}

};

});

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 文件
    +关注

    关注

    1

    文章

    567

    浏览量

    24758
  • JSON
    +关注

    关注

    0

    文章

    119

    浏览量

    6977

原文标题:还在直接用JWT做鉴权?JJWT真香

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何才能有效地针对性地对电气安全问题进行管理呢?#电工

    电气安全
    jf_55902079
    发布于 :2024年12月17日 15:23:29

    智能安全配电装置在临时展会场所中如何保证用电安全

    与敷设、设备的维护和管理等方面介绍了其安全保障技术,以保证此临时类场所中用电的安全。 【关键词】 临时展会、展摊;电气安全;智能安全配电装置
    的头像 发表于 12-12 09:17 110次阅读
    智能<b class='flag-5'>安全</b>配电装置在临时展会场所中如何<b class='flag-5'>保证</b>用电<b class='flag-5'>安全</b>

    tlv320aic3101怎样才能在使用AGC效果的同时,保证SINAD参数的良好?

    正常情况下,输入越大, SINAD参数会越好,所以不知道怎样才能在使用AGC效果的同时,保证SINAD参数的良好?具体应该调整哪些参数,如何调整?非常希望能够得到给位的帮助,谢谢!!
    发表于 11-06 06:51

    3分钟即被远程控制!智驾安全如何保证

    2024年10月24日,在GEEKCON大会上,一支安全团队通过现场演示的方式展示了如何破解一辆智能汽车的防护系统,利用远程控制手段解锁并启动了车辆。该演示揭示了智能汽车在车联网系统中潜在的网络安全
    的头像 发表于 10-28 09:29 294次阅读
    3分钟即被远程控制!智驾<b class='flag-5'>安全</b>如何<b class='flag-5'>保证</b>?

    无人叉车的安全性能如何保证?有哪些防护机制?

    无人叉车通过集成多种高精度传感器、先进的控制系统和智能避障算法,实现了高精度定位与自主导航,确保了作业过程中人员与设备的安全。以下是无人叉车的主要安全防护机制: 一、传感器防护 无人叉车配备了多种
    的头像 发表于 10-23 13:25 173次阅读

    如何保证备自投装置可靠性和稳定性

    备用电源自动投入装置(简称备自投)是一种保证配电系统可靠、连续供电的安全设备,因此它的可靠性和稳定性直接决定了系统的供电质量,那么该如何保证备自投装置的可靠性和稳定性呢?今天从专业的角度和大家聊一聊。
    的头像 发表于 10-17 17:44 224次阅读
    如何<b class='flag-5'>保证</b>备自投装置可靠性和稳定性

    什么样的激光雷达才能让AEB更安全

    所谓“道路万千条,安全第一条”,汽车安全一直是消费者在选车时的关键考虑因素之一。为了满足用户对安全的需求,汽车的主动安全功能也在不断地进化。
    的头像 发表于 09-27 11:31 499次阅读
    什么样的激光雷达<b class='flag-5'>才能</b>让AEB更<b class='flag-5'>安全</b>

    工业交换机如何保证数据的访问安全

    在现代工业自动化环境中,工业交换机作为关键的网络设备,扮演着数据传输和信息交互的重要角色。为了确保数据的访问安全,工业交换机不仅具备高效的转发性能,还集成了多层次的安全防护机制,以抵御各种潜在的网络威胁。
    的头像 发表于 09-19 16:18 232次阅读
    工业交换机如何<b class='flag-5'>保证</b>数据的访问<b class='flag-5'>安全</b>

    吉利:没有任何一家汽车制造商能够保证电池系统的100%安全

    近日,吉利控股集团的高层管理者沈源先生,在其公开言论中深刻指出了电动汽车电池安全性的复杂性与挑战性。他直言不讳地表示,基于物理学的客观规律,没有任何一家汽车制造商能够绝对保证电池系统的100%安全,这一坦诚态度彰显了行业对
    的头像 发表于 07-13 15:49 2083次阅读

    究竟FPC上的焊盘间距做多大才能保证阻焊桥

    都说PCB上焊盘间距做到8mil,保证绿油桥是没有问题,为什么FPC也是同样的设计, PCBA锡膏印刷后连锡短路,是焊接厂工艺能力不足,还是FPC设计出了问题,请走进今天的案例分析,一起为您揭谜。
    的头像 发表于 04-07 10:33 1401次阅读
    究竟FPC上的焊盘间距做多大<b class='flag-5'>才能</b><b class='flag-5'>保证</b>阻焊桥

    请问NFC数据传输如何保证数据安全

    NFC数据传输如何保证数据安全
    发表于 04-07 06:18

    浅谈智慧校园的用电安全管理分析及产品应用

    浅谈智慧校园的用电安全管理分析及产品应用 张颖姣 摘要:阐述校园安全用电管理的特点,存在的问题,应对策略,包括在实习实训和维修保养中的安全用电、提升电气保证设备
    的头像 发表于 03-13 10:09 313次阅读
    浅谈智慧校园的用电<b class='flag-5'>安全</b>管理分析及产品应用

    什么是JWTJWT由哪些部分组成?JWT如何进行用户认证?

    JWT(JSON Web Token)是一个开放的行业标准(RFC 7519),自身包含了身份验证所需要的所有信息,因此我们的服务器不需要存储用户Session信息。
    的头像 发表于 02-25 09:44 3811次阅读
    什么是<b class='flag-5'>JWT</b>?<b class='flag-5'>JWT</b>由哪些部分组成?<b class='flag-5'>JWT</b>如何进行用户认证?

    安全继电器和普通继电器区别 安全继电器应用案例

    安全继电器具有内置的故障检测机制和逻辑,以实时监测继电器本身的运行状态。在发生故障时,安全继电器会采取相应的断开或切断操作,以保证人员和设备的安全
    的头像 发表于 02-06 15:57 3144次阅读
    <b class='flag-5'>安全</b>继电器和普通继电器区别 <b class='flag-5'>安全</b>继电器应用案例

    AD6645的底噪要做到什么程度才能最大限度的保证adc的有效位数?

    我以前用过AD6645,现在在用ad9238画板子,做中频信号采集。板子上还有高速FPGA以及DSP。由于adc的位数比较高,14bit和12bit,我不太清楚板子的底噪要做到什么程度才能最大
    发表于 01-09 07:45