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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值