抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

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();
// UserVO userVO=AuthUtil.<UserVO>getUser();
return R.ok(user);
}

// 暴露接口使用注解
@Expose
@GetMapping("/info")
public void info() {
// ...
}
}

3.自定义配置

常用自定义的配置

1
2
3
4
5
auth:
header: custom_token #请求头参数,如{"custom_token":"asfoav5h35v43692"}
cache-prefix: xxx #缓存redis的key
timeout: 3600 #登录有效期,单位秒
reset-timeout: true #是否自动续租token过期时间

三、接口加密

@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 #rsa私钥,配置该项则开启
timeout: 60 #允许超时时间,单位秒,默认为3分钟

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 {
// 必须拥有'add'权限才可访问
@Permission("add")
@GetMapping("/add")
public void add() {
}

// 必须拥有'edit'权限才可访问
@Permission("edit")
@GetMapping("/edit")
public void edit() {
}

// 必须拥有'edit'和'del'权限才可访问
@Permission({"edit", "del"})
@GetMapping("/edit/and/del")
public void editAndDel() {
}

// 拥有'del_all'或者'administrator'权限即可访问
@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不仅仅可加在接口上,只要是spring容器接管的都可以(原理使用aop实现)
@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 {
// 必须拥有'sys_user_add'权限才可访问
@Permission("add")
@GetMapping("/add")
public void add() {
}

// 必须拥有'sys_user_edit'权限才可访问
@Permission("edit")
@GetMapping("/edit")
public void edit() {
}

// 必须拥有'sys_role_edit'权限才可访问
// prefix为false时,不会拼接类上@PermissionPrefix的前缀
@Permission(value = "sys_role_edit", prefix = false)
@GetMapping("/role/edit")
public void roleEdit() {
}
}

3.实现带鉴权功能的BaseController

一般业务都会有crud接口,所以我们可以抽离出BaseController结合PermissionPrefix快速实现crud接口并且拥有接口鉴权功能

  • BaseController
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();
}
}
  • UserController
1
2
3
4
5
6

@RestController
@PermissionPrefix("user_")
@RequestMapping("user")
public class UserController extends BaseController<UserService, User> {
}

此时实现了用户新增和编辑功能,并且新增和编辑需要拥有权限分别是user_adduser_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 {
// 每秒最多请求10次
@RateLimit(10)
@GetMapping("/rate1")
public void rate1() {
// ...
}

// 每小时最多请求50次
@RateLimit(hour = 50)
@GetMapping("/rate2")
public void rate2() {
// ...
}

// 每秒最多10次且每分钟最多20次
@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) {
// 此处可以将日志自行保存到mysql等
}
}

auth-spring-boot-starter项目仓库地址

目前此项目皆由作者个人维护,因此视角面可能是狭隘的,欢迎大家多提提意见和建议、寻找bug寻找漏洞,帮助框架更加完善~

评论