SpringBoot 集成 auth-spring-boot-starter 快速实现权限拦截
auth-spring-boot-starter 是一个基于token鉴权的权限框架,不像shiro或oauth2重繁琐,通过开箱即用的方式,快速实现token登录及接口鉴权等功能
一、集成
1.引入依赖
1 2 3 4 5 6
| <dependency> <groupId>com.seepine</groupId> <artifactId>auth-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency>
|
2.注解简介
- @Expose/@NotExpose 暴露/不暴露接口
- @Secret/@NotSecret 接口请求头加密,可大大避免通过F12得知接口地址和传参恶意调用
- @Permission/@PermissionPrefix 接口鉴权,快速实现用户、角色、权限功能
- @RateLimit 接口速率限制,支持秒/分/时/天,可用于例如短信/邮箱发送、注册、下单、支付等,被恶意刷量
- @Log 快速实现日志记录
二、登录鉴权
@Login/@Expose/@NotExpose
1.获取token
在登录接口使用注解@Expose
,获取到用户信息后调用AuthUtil.loginSuccess,该方法将会返回用户token 并且可传入不同用户信息,比如User,比如UserVo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Controller { @Expose @GetMapping("/login/{username}/{password}") public R login(@PathVariable String username, @PathVariable String password) { User user = userService.getByUsername(username, password); return R.ok(AuthUtil.loginSuccess(user)); }
@Expose @GetMapping("/login/{code}") public R login(@PathVariable String code) { UserVO user = userService.getByCode(code); return R.ok(AuthUtil.loginSuccess(user)); } }
|
2.请求接口
请求接口时,请求头中加上{‘token’:’xxxxxxxxxxxxxxxxxx’}其中token后的字符串由登录接口获得
,即可在方法中通过AuthUtil.getUser()
获取到当前登录者的用户信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Controller { @GetMapping("/info") public R info() { Object obj = AuthUtil.getUser(); User user = AuthUtil.<User>getUser(); return R.ok(user); } @Expose @GetMapping("/info") public void info() { } }
|
3.自定义配置
常用自定义的配置
1 2 3 4 5
| auth: header: custom_token cache-prefix: xxx timeout: 3600 reset-timeout: true
|
三、接口加密
@Secret/@NotSecret
一般用于高安全性接口,例如验证码发送/支付接口等。通过此方式无法完全避免安全性问题,但可一定程度上增加接口被盗刷情况,建议勤更换公私钥。
1.获取RSA公私钥
若自己有rsa公私钥可跳过此步骤
1 2 3 4 5 6 7
| class Main { public static void main(String[] args) { RSA rsa = new RSA(); rsa.getPublicKey(); rsa.getPrivateKey(); } }
|
2.配置解密私钥
1 2 3 4
| auth: secret: rsa-private-key: xxx timeout: 60
|
3.指定接口需要密文鉴权
1 2 3 4 5 6 7 8 9
| @RestController public class Controller { @Secret @GetMapping("/pay") public void pay() { } }
|
4.前端附带加密请求头
其中secret的值为公钥加密时间戳的值,并且时间戳与后端时间默认相差不超过4小时
1 2 3
| { "secret": "xxxxxxxxxxxxxxxxxx" }
|
5.重写规则
若想自定义规则,可实现该接口并注入bean即可
1 2 3
| public interface AuthSecretService { void verify(String secretValue) throws AuthException; }
|
四、接口鉴权
@Permission/@PermissionPrefix
使用接口鉴权注解时,需要在登陆时传入用户所拥有的权限list,例如AuthUtil.loginSuccess(user,permissionList)
1.单独使用Permission
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| @RestController public class Controller { @Permission("add") @GetMapping("/add") public void add() { }
@Permission("edit") @GetMapping("/edit") public void edit() { }
@Permission({"edit", "del"}) @GetMapping("/edit/and/del") public void editAndDel() { }
@Permission(or = {"del_all", "administrator"}) @GetMapping("/del/all") public void delAll() { }
@Resource Service service;
@GetMapping("/del/all") public void func() { service.func(); }
}
@Service class Service { @Permission("service_permission_a") public void func() { } }
|
2.使用PermissionPrefix为所有权限加上前缀
正常使用场景中,一般的权限会如同xxx_add
,yyy_add
,zzz_add
,xxx_edit
这般,前面带有模块或业务的标识,当然使用@Permission
直接指定具体权限也是可以的例如@Permission("xxx_add")
,但是一般业务也会按Controller划分,同一个Controller中所有接口的权限前缀基本是相同的,因此可通过@PermissionPrefix
简化代码,具体如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @PermissionPrefix("sys_user_") @RestController public class Controller { @Permission("add") @GetMapping("/add") public void add() { }
@Permission("edit") @GetMapping("/edit") public void edit() { }
@Permission(value = "sys_role_edit", prefix = false) @GetMapping("/role/edit") public void roleEdit() { } }
|
3.实现带鉴权功能的BaseController
一般业务都会有crud接口,所以我们可以抽离出BaseController结合PermissionPrefix快速实现crud接口并且拥有接口鉴权功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class BaseController<S, T> { @Resource S service;
@Permission("add") @GetMapping("/add") public void add(@RequestBody T entity) { service.add(entity); }
@Permission("edit") @GetMapping("/edit") public void edit() { service.edit(); } }
|
1 2 3 4 5 6
| @RestController @PermissionPrefix("user_") @RequestMapping("user") public class UserController extends BaseController<UserService, User> { }
|
此时实现了用户新增和编辑功能,并且新增和编辑需要拥有权限分别是user_add
和user_edit
,并且当重写父类方法时,权限注解仍然有效
五、接口限速
@RateLimit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @RestController public class Controller { @RateLimit(10) @GetMapping("/rate1") public void rate1() { }
@RateLimit(hour = 50) @GetMapping("/rate2") public void rate2() { }
@RateLimit(second = 10, minute = 20) @GetMapping("/rate3") public void rate3() { } }
|
六、日志记录
@Log
1.注解使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @RestController public class UserController { @Log("新增用户") @GetMapping("/add") public void add() { }
@Log(title = "编辑用户", content = "管理员编辑用户") @GetMapping("/edit") public void edit() { }
@Log("删除用户") @GetMapping("/del") public void rate3() { throw new Exception("用户不存在,删除失败"); } }
|
2.日志存库
1 2 3 4 5 6 7 8
| @Component public class MyAuthLogService implements AuthLogService { @Override public void save(LogEvent logEvent) { } }
|
auth-spring-boot-starter项目仓库地址
目前此项目皆由作者个人维护,因此视角面可能是狭隘的,欢迎大家多提提意见和建议、寻找bug寻找漏洞,帮助框架更加完善~