jwt配置 restful_SpringBoot实现JWT保护前后端分离RESTful API

本文将用不到100行Java代码, 教你如何在Spring Boot里面用JWT保护RESTful api.

登录前

登录之后即可得到正确结果

登陆后

1. 什么是JWT

了解JWT的同学可以跳过这一部分

废话少说, 我们先看看什么是JWT. JSON Web Token其实就是一个包含认证数据的JSON, 大概长这样子

分三个部分,

第一部分{"alg":"HS512"}是签名算法

第二部分 {"exp":1495176357,"username":"admin"}是一些数据(你想放什么都可以), 这里有过期日期和用户名

第三部分')4'7�6-DM�(�H6fJ::$c���a4�~tI2%Xd-�$nL(l非常重要,是签名Signiture, 服务器会验证这个以防伪造. 因为JWT其实是明文传送, 任何人都能篡改里面的内容. 服务端通过验证签名, 从而确定这个JWT是自己生成的.

原理也不是很复杂, 我用一行代码就能表示出来

首先我们将JWT第一第二部分的内容, 加上你的秘钥(key或者叫secret), 然后用某个算法(比如hash算法)求一下, 求得的内容就是你的签名. 验证的时候只需要验证你用JWT算出来的值是否等于JWT里面的签名.

因为别人没有你的key, 所以也就没法伪造签名.

简单粗暴一行代码解释什么是签名:

intsigniture =("{alg:HS512}{exp:1495176357,username:admin}"+key).hashCode();

最后附上签名,得到完整的JWT:

{"alg":"HS512"}{"exp":1495176357,"username":"admin"}')4'7�6-DM�(�H6fJ::$c���a4�~tI2%Xd-�$nL(l

为了方便复制和使用, 通常我们都是把JWT用base64编码之后放在http的header里面, 并且每一次呼叫api都附上这个JWT, 并且服务器每次也验证JWT是否过期

通常我们用到的JWT:

Base64编码后:eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE0OTUxNzYzNTcsInVzZXJuYW1lIjoiYWRtaW4ifQ.mQtCfLKfI0J7c3HTYt7kRN4AcoixiUSDaZv2ZKOjq2JMZjBhf1DmE0Fn6PdEkyJZhYZJTMLaIPwyR-uu6BMKGw

2. 三个class实现JWT

整个demo一共有三个class

Application.java JwtAuthenticationFilter.java 和 JwtUtil.java

2.1首先我们看一看Application.java

第一步创建一个hello world api

@GetMapping("/protected")public@ResponseBodyObjecthellWorld(){return"Hello World! This is a protected api";}

第二步创建一个 login的api, 我们会验证用户的密码, 如果正确, 那么我们会返回生成jwt. 这时前端拿到的这个jwt就类似于拿到了一个临时的密码, 之后所有的HTTP RESTful api请求都附上这个"临时密码"即可.(专业术语叫令牌/token)

@PostMapping("/login")publicObjectlogin(HttpServletResponseresponse,@RequestBodyfinalAccountaccount)throwsIOException{if(isValidPassword(account)){Stringjwt =JwtUtil.generateToken(account.username);returnnewHashMap(){{put("token",jwt);}};}else{returnnewResponseEntity(HttpStatus.UNAUTHORIZED);}}

登录效果如下图

最后我们再注册一个检验jwt的过滤器Filter, 通过这个过滤器Filter实现对每个Rest api请求都验证jwt的功能. 这个JwtAuthenticationFilter继承了OncePerRequestFilter, 任何请求都会先经过我们的filter, 然后我们会选择让那些有合法jwt的请求通过我们的filter.

@BeanpublicFilterRegistrationBeanjwtFilter(){finalFilterRegistrationBeanregistrationBean =newFilterRegistrationBean();JwtAuthenticationFilterfilter =newJwtAuthenticationFilter();registrationBean.setFilter(filter);returnregistrationBean;}

2.2然后我们看一下JwtAuthenticationFilter.java

这里我们继承了OncePerRequestFilter, 保证了用户请求任何资源都会运行这个doFilterInternal. 这里我们会从HTTP Header里面截取JWT, 并且验证JWT的签名和过期时间, 如果有问题, 我们会返回HTTP 401错误.

PS: 这里有个情况就是用户登录/login前是没有jwt的, 所以我们要让登录的请求

publicclassJwtAuthenticationFilterextendsOncePerRequestFilter{//......一些不重要的代码......@OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{try{if(isProtectedUrl(request)){Stringtoken =request.getHeader("Authorization");//检查jwt令牌, 如果令牌不合法或者过期, 里面会直接抛出异常, 下面的catch部分会直接返回JwtUtil.validateToken(token);}}catch(Exceptione){response.sendError(HttpServletResponse.SC_UNAUTHORIZED,e.getMessage());return;}//如果jwt令牌通过了检测, 那么就把request传递给后面的RESTful apifilterChain.doFilter(request,response);}//......一些不重要的代码......}

2.3最后我们看一下JwtUtil.java

这里就两个函数, 第一个函数生成一个有效期1000小时的jwt

public static String generateToken(String username)

第二个函数是验证JWT是否有效, 如果JWT有效则返回用户名, 否则抛出Exception

public static void validateToken(String token)

这里的代码都非常简洁就十几行, 使用的都是现成的包, 建议直接看源代码.

3.测试

这就是呼叫api的效果

正确jwt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/348096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

fusion构建器代码语法_构建器模式:适用于代码,适用于测试

fusion构建器代码语法我发现构建器设计模式偶尔在代码中有用,但在测试中经常有用。 本文简要概述了该模式,然后介绍了在测试中使用该模式的一个有效示例。 请参阅github中的代码。 生成器模式的背景 根据GoF的书 ,构建器设计模式用于“将复杂…

6000毫安以上智能手机_三星超长续航神机,6000毫安+128GB,上市半年不到跌至1499...

现在的手机是越来越智能了,无论是苹果还是安卓,基本都能为用户的生活添加几分乐趣,因为,当我们感到无聊时,基本都可以通过智能手机来打发时间。据我所知,不少人在用智能手机时都有个困扰,就是续…

使用RabbitMQ进行消息传递

RabbitMQ是一个强大的消息代理,可用于实现不同的消息传递模式。 即使有出色的教程 (使用不同的语言和框架),也很难理解这些概念。 在这篇文章中,我想展示一些可以用RabbitMQ实现的不同范例,以及为什么要为某…

android 为什么fragment在调用hide方法后没有生效_Android 多 Fragment 切换优化

code小生,一个专注 Android 领域的技术平台公众号回复 Android 加入我的安卓技术群作者:DDDong丶链接:https://www.jianshu.com/p/c8e8a0249911声明:本文已获DDDong丶授权发表,转发等请联系原作者授权问题分析一直在简书里看别人的…

mysql如何查看远程用户_MySQL系列(十)--用户权限及远程访问

本文基于MySQL8.0,记录一下完整的远程访问的过程,以及这个过程中可能遇到的问题,MySQL运行在阿里云服务器,操作系统:CentOS 7.6 64位顺便说下,买服务器还是要双十二这种拉新活动再买,用一个新的…

spring mvc拆分_Spring集成–强大的拆分器聚合器

spring mvc拆分健壮是什么意思? 在本文的上下文中,健壮性是指在不立即返回给调用者的情况下管理流中的异常条件的能力。 在某些处理方案中, n个 m个回答足以做出结论。 通常具有这些趋势的示例处理场景是: 财务,保…

mysql typeindex_explain mysql的type字段,索引的类型

4.type这列很重要,显示了连接使用了哪种类别,有无使用索引.从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL(1).system这是const联接类型的一个特例。表仅有一行满足条件.如下(t3表上的id是 primary key)mysql> explain select * from (select * from t3 …

JasperReports:棘手的部分

如果您使用Java进行编程的时间足够长,则有可能需要为业务用户生成报告。 就我而言,我已经看到几个项目使用JasperReports库来生成PDF和其他文件格式的报告。 最近,我荣幸地观察了Mike和他的团队使用上述报告库及其面临的挑战。 简而言之Jasp…

win mysql 2003错误_windows MySql 报1067错误 2003错误

1067错误原因是我把安装mysql的目录的名字改了。但是位于目录里面的my.ini配置文件没有修改,玛德我真傻逼。把my.ini的#Path to installation directory. All paths are usually resolved relative to this.basedir"D:/My_MySQL/"这下面一行的路径名改成目…

java heroku_Heroku和Java –从新手到初学者,第1部分

java heroku最近,我听说Heroku允许在Cedar堆栈中部署Java应用程序。 由于没有真正的软件构想,我决定尝试一下,仅配置SOMETHING以在Heroku上运行。 我对ReST有所了解(我仍然想学习并练习),所以我决定我的第…

mysql 合服_风云私服合区的方法详解(mysql数据库合并)

只能合并帐号,MY的库不能合并。倒数据前请留好备份,防止发生以外,破坏你得数据,切忌.1)首先确认你的机器上必须装MySQL 以及 mysql-connector-odbc-5.1.1-win32.msimysql-connector-odbc-5.1.1-win32.msi 就是 MySQL ODBC 5.1,你可…

mysql自定义数据类型_MySQL中的数据类型

一.MySQL中的数值类型分类MySQL中数值类型主要有三类:数字类型,字符串类型,时间类型。1.数字类型1.1整数tinyint 1字节smallint 2字节mediumint 3字节int 4字节bigint …

分布式系统开发注意点_分布式系统开发注意事项

分布式系统开发注意点开发分布式软件系统时,要考虑许多因素。 如果您甚至不知道第一句话中我在说什么,那么让我为您提供一些见解,示例以及有关分布式系统的实例。 总览 分布式系统是指多个物理硬件设备与单独的离散用户交互并通过这些硬件设…

String#repeat来到Java吗?

JDK-8197594 (“ String#repeat”)在其“描述”中包括以下内容:“长期以来,一直要求一种用于重复字符序列的String方法,没有后续操作。” 可以在JDK-8197594的“问题链接”中找到有关String类中用于重复字符…

mysql 什么是幻读_何为幻读?MySQL又是如何解决幻读的?

一、什么是幻读在一次事务里面,多次查询之后,查询的结果集的个数不一致的情况叫做幻读。而多出来或者少的哪一行被叫做 幻行二、为什么要解决幻读在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的一致性。三、…

电子电气架构——车载ECU刷写工具vFlash简介

电子电气架构——车载ECU刷写工具vFlash简介 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值&a…

mysql执行系统命令_mysql 命令行执行 sql

1.直接输入sql执行MySQL> select now();---------------------| now() |---------------------| 2013-09-18 13:55:45 |---------------------1 row in set (0.00 sec)2.执行编写好的sql脚本mysql> source /home/1.sql---------------------| now() |-------------------…

jboss7.1.1 部署_在JBoss AS 7上部署BroadleafCommerce 2.0

jboss7.1.1 部署前2个步骤实际上与Broadleaf无关&#xff0c;但是提到该步骤是为了使其易于执行&#xff08;复制/粘贴&#xff09;这些步骤。 步骤&#xff03;1&#xff1a;在JBoss AS中配置数据源。 <datasource jta"true" jndi-name"java:jboss/datasou…

java中n次方怎么表示_java如何计算一个数的n次方

java递归算法&#xff0c;代码如下&#xff1a;public class Test3 { public double zhishu(double x,double y){ if(y>0){ return x*zhishu(x,y-1); }else if(y<0){ return (x*zhishu(x,-y-1)); }else{ return 1; } } public double fuzhishu(…

枚举集合的EnumSet

在上一篇博客文章中&#xff0c;我们发现了EnumMap用于带有枚举键的映射。 您可能已经观察到&#xff0c;还有一个专门针对枚举优化的Set &#xff1a; EnumSet 。 我们再次定义一个CoffeeType枚举&#xff1a; public enum CoffeeType {ESPRESSO, POUR_OVER, FRENCH_PRESS, …