1
1
# Shiro+JWT+Spring Boot Restful简易教程
2
2
3
- ### 序言
3
+ ## 序言
4
4
5
5
我也是半路出家的人,如果大家有什么好的意见或批评,请务必` issue ` 下。
6
6
7
7
项目地址:[ https://github.com/Smith-Cruise/Spring-Boot-Shiro ] ( https://github.com/Smith-Cruise/Spring-Boot-Shiro ) 。
8
8
9
9
如果想要直接体验,直接` clone ` 项目,运行` mvn spring-boot:run ` 命令即可进行访问。网址规则自行看教程后面。
10
10
11
- ### 特性
11
+ 如果想了解Spring Security可以看[ Spring Boot 2.0+Srping Security+Thymeleaf的简易教程] ( https://github.com/Smith-Cruise/Spring-Boot-Security-Thymeleaf-Demo )
12
+
13
+ ## 特性
12
14
13
15
* 完全使用了Shiro的注解配置,保持高度的灵活性。
14
16
* 放弃Cookie,Session,使用JWT进行鉴权,完全实现无状态鉴权。
15
17
* JWT密钥支持过期时间。
16
18
* 对跨域提供支持
17
19
18
- ### 准备工作
20
+ ## 准备工作
19
21
20
22
在开始本教程之前,请保证已经熟悉以下几点。
21
23
26
28
27
29
简要的说明下我们为什么要用JWT,因为我们要实现完全的前后端分离,所以不可能使用` session ` ,` cookie ` 的方式进行鉴权,所以JWT就被派上了用场,你可以通过一个加密密钥来进行前后端的鉴权。
28
30
29
- ### 程序逻辑
31
+ ## 程序逻辑
30
32
31
33
1 . 我们POST用户名与密码到` /login ` 进行登入,如果成功返回一个加密token,失败的话直接返回401错误。
32
34
2 . 之后用户访问每一个需要权限的网址请求必须在` header ` 中添加` Authorization ` 字段,例如` Authorization: token ` ,` token ` 为密钥。
33
35
3 . 后台会进行` token ` 的校验,如果有误会直接返回401。
34
36
35
- ### Token加密说明
37
+ ## Token加密说明
36
38
37
39
- 携带了` username ` 信息在token中。
38
40
- 设定了过期时间。
39
41
- 使用用户登入密码对` token ` 进行加密。
40
42
41
- ### Token校验流程
43
+ ## Token校验流程
42
44
43
45
1 . 获得` token ` 中携带的` username ` 信息。
44
46
2 . 进入数据库搜索这个用户,得到他的密码。
45
47
3 . 使用用户的密码来检验` token ` 是否正确。
46
48
47
- ### 准备Maven文件
49
+ ## 准备Maven文件
48
50
49
51
新建一个Maven工程,添加相关的dependencies。
50
52
110
112
111
113
注意指定JDK版本和编码
112
114
113
- ### 构建简易的数据源
115
+ ## 构建简易的数据源
114
116
115
117
为了缩减教程的代码,我使用` HashMap ` 本地模拟了一个数据库,结构如下
116
118
123
125
124
126
之后再构建一个` UserService ` 来模拟数据库查询,并且把结果放到` UserBean ` 之中。
125
127
126
- ###### UserService.java
128
+ *** UserService.java***
127
129
128
130
``` java
129
131
@Component
@@ -146,7 +148,7 @@ public class UserService {
146
148
}
147
149
```
148
150
149
- ###### UserBean.java
151
+ *** UserBean.java***
150
152
151
153
``` java
152
154
public class UserBean {
@@ -192,7 +194,7 @@ public class UserBean {
192
194
}
193
195
```
194
196
195
- ### 配置JWT
197
+ ## 配置JWT
196
198
197
199
我们写一个简单的JWT加密,校验工具,并且使用用户自己的密码充当加密密钥,这样保证了token 即使被他人截获也无法破解。并且我们在` token ` 中附带了` username ` 信息,并且设置密钥5分钟就会过期。
198
200
@@ -256,9 +258,9 @@ public class JWTUtil {
256
258
}
257
259
```
258
260
259
- ### 构建URL
261
+ ## 构建URL
260
262
261
- ###### ResponseBean.java
263
+ *** ResponseBean.java***
262
264
263
265
既然想要实现restful,那我们要保证每次返回的格式都是相同的,因此我建立了一个` ResponseBean ` 来统一返回的格式。
264
266
@@ -306,7 +308,7 @@ public class ResponseBean {
306
308
}
307
309
```
308
310
309
- ###### 自定义异常
311
+ *** 自定义异常***
310
312
311
313
为了实现我自己能够手动抛出异常,我自己写了一个` UnauthorizedException.java `
312
314
@@ -322,7 +324,7 @@ public class UnauthorizedException extends RuntimeException {
322
324
}
323
325
```
324
326
325
- ###### URL结构
327
+ *** URL结构***
326
328
327
329
| URL | 作用 |
328
330
| ------------------- | ----------------------- |
@@ -332,7 +334,7 @@ public class UnauthorizedException extends RuntimeException {
332
334
| /require_role | admin的角色用户才可以登入 |
333
335
| /require_permission | 拥有view和edit权限的用户才可以访问 |
334
336
335
- ###### Controller
337
+ *** Controller***
336
338
337
339
``` java
338
340
@RestController
@@ -394,7 +396,7 @@ public class WebController {
394
396
}
395
397
```
396
398
397
- ###### 处理框架异常
399
+ *** 处理框架异常***
398
400
399
401
之前说过restful要统一返回的格式,所以我们也要全局处理` Spring Boot ` 的抛出异常。利用` @RestControllerAdvice ` 能很好的实现。
400
402
@@ -434,11 +436,11 @@ public class ExceptionController {
434
436
435
437
```
436
438
437
- ### 配置Shiro
439
+ ## 配置Shiro
438
440
439
441
大家可以先看下官方的 [ Spring-Shiro] ( http://shiro.apache.org/spring.html ) 整合教程,有个初步的了解。不过既然我们用了` Spring-Boot ` ,那我们肯定要争取零配置文件。
440
442
441
- ###### 实现JWTToken
443
+ *** 实现JWTToken***
442
444
443
445
` JWTToken ` 差不多就是` Shiro ` 用户名密码的载体。因为我们是前后端分离,服务器无需保存用户状态,所以不需要` RememberMe ` 这类功能,我们简单的实现下` AuthenticationToken ` 接口即可。因为` token ` 自己已经包含了用户名等信息,所以这里我就弄了一个字段。如果你喜欢钻研,可以看看官方的` UsernamePasswordToken ` 是如何实现的。
444
446
@@ -464,7 +466,7 @@ public class JWTToken implements AuthenticationToken {
464
466
}
465
467
```
466
468
467
- ###### 实现Realm
469
+ *** 实现Realm***
468
470
469
471
` realm ` 的用于处理用户是否合法的这一块,需要我们自己实现。
470
472
@@ -531,7 +533,7 @@ public class MyRealm extends AuthorizingRealm {
531
533
532
534
在` doGetAuthenticationInfo ` 中用户可以自定义抛出很多异常,详情见文档。
533
535
534
- ###### 重写Filter
536
+ *** 重写Filter***
535
537
536
538
所有的请求都会先经过` Filter ` ,所以我们继承官方的` BasicHttpAuthenticationFilter ` ,并且重写鉴权的方法。
537
539
@@ -623,7 +625,7 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
623
625
624
626
` getSubject(request, response).login(token); ` 这一步就是提交给了` realm ` 进行处理
625
627
626
- ###### 配置Shiro
628
+ *** 配置Shiro***
627
629
628
630
``` java
629
631
@Configuration
@@ -702,7 +704,7 @@ public class ShiroConfig {
702
704
703
705
里面URL规则自己参考文档即可http://shiro.apache.org/web.html 。
704
706
705
- ### 总结
707
+ ## 总结
706
708
707
709
我就说下代码还有哪些可以进步的地方吧
708
710
0 commit comments