SpringBoot uses Sa-Token to complete the annotation authentication function

Annotation authentication - gracefully separate authentication from business code. In this article, we will introduce how to complete permission verification through annotations in Sa-Token.

Sa-Token is a lightweight java authority authentication framework, which mainly solves a series of authority-related issues such as login authentication, authority authentication, single sign-on, OAuth2, and microservice gateway authentication. Gitee open source address: gitee.com/dromara/sa-…

1. List of Sa-Token authentication annotations

The authentication annotations provided by Sa-Token include but are not limited to the following:

  • @SaCheckLogin: Login verification - this method can only be entered after login.
  • @SaCheckRole("admin"): Role check - must have the specified role ID to enter this method.
  • @SaCheckPermission("user:add"): Permission verification - you must have the specified permission to enter this method.
  • @SaCheckSafe: Level 2 authentication verification - you must enter this method after level 2 authentication.
  • @SaCheckBasic: HttpBasic verification - this method can only be entered after passing the Basic authentication.
  • @SaCheckDisable("comment"): Account service ban check - check whether the specified service of the current account is banned.
  • @SaIgnore: Ignore verification——Indicates that the modified method or class does not need to perform annotation authentication and routing interceptor authentication.

First introduce the Sa-Token dependency in the project:

xml复制代码<!-- Sa-Token 权限认证 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.34.0</version>
</dependency>

Note: If you are using SpringBoot 3.x, just change sa-token-spring-boot-starter to sa-token-spring-boot3-starter.

2. Login authentication

Sa-Token uses the global interceptor to complete the annotation authentication function. In order not to bring unnecessary performance burden to the project, the interceptor is turned off by default. Therefore, in order to
use annotation authentication, you must manually set the global interceptor of Sa-Token Register with your project .

Taking SpringBoot2.0 as an example, create a new configuration class SaTokenConfigure.java

java复制代码@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
	// 注册 Sa-Token 拦截器,打开注解式鉴权功能 
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 注册 Sa-Token 拦截器,打开注解式鉴权功能 
		registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");	
	}
}

Make sure that this class is scanned by the springboot startup class.

Create a new LoginController and add the following code:

java复制代码/**
 * 登录认证注解测试
 */
@RestController
public class LoginController {

    // 访问 home 页,登录后才能访问  ---- http://localhost:8081/home
    @SaCheckLogin
    @RequestMapping("home")
    public SaResult home() {
        return SaResult.ok("访问成功,此处为登录后才能看到的信息");
    }

    // 登录接口  ---- http://localhost:8081/doLogin?name=zhang&pwd=123456
    @RequestMapping("doLogin")
    public SaResult doLogin(String name, String pwd) {
        // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对
        if("zhang".equals(name) && "123456".equals(pwd)) {
            StpUtil.login(10001);
            return SaResult.ok("登录成功");
        }
        return SaResult.error("登录失败");
    }

}

Start the project and access the resource interface for the first time:

text复制代码http://localhost:8081/home

returns as follows:

json复制代码{
	"code": 500,
	"msg": "未能读取到有效Token",
	"data": null
}

The session is not logged in, so the resource cannot be accessed.

Now let's visit the login interface again:

text复制代码http://localhost:8081/doLogin?name=zhang&pwd=123456

returns as follows:

json复制代码{
	"code": 200,
	"msg": "登录成功",
	"data": null
}

After the login is successful, let's go to access the resource interface:

url复制代码http://localhost:8081/home

returns as follows:

json复制代码{
	"code": 200,
	"msg": "访问成功,此处为登录后才能看到的信息",
	"data": null
}

Through the login authentication verification, the information is successfully obtained!

3. Authority Authentication & Role Authentication

First, we need to implement the StpInterface interface to tell the framework which permission codes the specified account has.

java复制代码/**
 * 自定义权限认证接口扩展,Sa-Token 将从此实现类获取每个账号拥有的权限码 
 * 
 * @author kong
 * @since 2022-10-13
 */
@Component	// 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 
public class StpInterfaceImpl implements StpInterface {

	/**
	 * 返回一个账号所拥有的权限码集合 
	 */
	@Override
	public List<String> getPermissionList(Object loginId, String loginType) {
		// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限
		List<String> list = new ArrayList<String>();	
		list.add("101");
		list.add("user.add");
		list.add("user.update");
		list.add("user.get");
		// list.add("user.delete");
		list.add("art.*");
		return list;
	}

	/**
	 * 返回一个账号所拥有的角色标识集合 
	 */
	@Override
	public List<String> getRoleList(Object loginId, String loginType) {
		// 本list仅做模拟,实际项目中要根据具体业务逻辑来查询角色
		List<String> list = new ArrayList<String>();	
		list.add("admin");
		list.add("super-admin");
		return list;
	}

}

Validation is done using the following two annotations:

  • @SaCheckPermission("user.add"): Check whether the current session has a certain permission.
  • @SaCheckRole("super-admin"): Check whether the current session has a certain role.
java复制代码/**
 * Sa-Token 注解鉴权示例 
 * 
 * @author kong
 * @since 2022-10-13
 */
@RestController
@RequestMapping("/at-check/")
public class AtCheckController {

	/*
	 * 前提1:首先调用登录接口进行登录
	 * 		---- http://localhost:8081/doLogin?name=zhang&pwd=123456
	 * 
	 * 前提2:项目在配置类中注册拦截器 SaInterceptor ,此拦截器将打开注解鉴权功能 
	 * 
	 * 前提3:项目实现了 StpInterface 接口,此接口会告诉框架指定账号拥有哪些权限码
	 * 
	 * 然后我们就可以使用以下示例中的代码进行注解鉴权了 
	 */
	
	// 权限校验   ---- http://localhost:8081/at-check/checkPermission
	//		只有具有 user.add 权限的账号才可以进入方法 
	@SaCheckPermission("user.add")
	@RequestMapping("checkPermission")
	public SaResult checkPermission() {
		// ... 
		return SaResult.ok();
	}

	// 角色校验   ---- http://localhost:8081/at-check/checkRole
	//		只有具有 super-admin 角色的账号才可以进入方法 
	@SaCheckRole("super-admin")
	@RequestMapping("checkRole")
	public SaResult checkRole() {
		// ... 
		return SaResult.ok();
	}
	
}

Test visits are available following the links provided in the code comments.

4. Set the verification mode

The @SaCheckRole and @SaCheckPermission annotations can set the verification mode, for example:

java复制代码// 注解式鉴权:只要具有其中一个权限即可通过校验 
@RequestMapping("atJurOr")
@SaCheckPermission(value = {"user-add", "user-all", "user-delete"}, mode = SaMode.OR)		
public SaResult atJurOr() {
	return SaResult.data("用户信息");
}

mode has two values:

  • SaMode.AND, mark a group of permissions, the session must have all of them to pass the verification.
  • SaMode.OR, mark a set of permissions, as long as the session has one of them, it can pass the verification.

5. Double "or verification" of role permissions

Assume the following business scenario: an interface can be invoked when it has the authority user.add or the role admin. how to write?

java复制代码// 角色权限双重 “or校验”:具备指定权限或者指定角色即可通过校验
@RequestMapping("userAdd")
@SaCheckPermission(value = "user.add", orRole = "admin")		
public SaResult userAdd() {
	return SaResult.data("用户信息");
}

The orRole field represents the secondary option when the authority authentication fails. As long as one of the two is successfully authenticated, the verification can be passed. There are three ways to write it:

  • Writing method 1: orRole = "admin", which means that you need to have the role admin.
  • Writing method 2: orRole = {"admin", "manager", "staff"}, which means that you can have one of the three roles.
  • Writing method 3: orRole = {"admin, manager, staff"}, which means that there must be three roles at the same time.

6. Secondary certification

java复制代码@RestController
@RequestMapping("/at/")
public class AtController {

	// 在当前会话完成二级认证  ---- http://localhost:8081/at/openSafe 
	@RequestMapping("openSafe")
	public SaResult openSafe() {
		StpUtil.openSafe(200); // 打开二级认证,有效期为200秒
		return SaResult.ok();
	}
	
	// 通过二级认证后,才可以进入  ---- http://localhost:8081/at/checkSafe 
	@SaCheckSafe
	@RequestMapping("checkSafe")
	public SaResult checkSafe() {
		return SaResult.ok();
	}

}

The second-level authentication must be opened through StpUtil.openSafe(1200) (the parameter is the validity period of the specified authentication, unit: second) before it can pass the check of @SaCheckSafe.

7. HttpBasic certification:

java复制代码@RestController
@RequestMapping("/at/")
public class AtController {

	// 通过Basic认证后才可以进入  ---- http://localhost:8081/at/checkBasic 
	@SaCheckBasic(account = "sa:123456")
	@RequestMapping("checkBasic")
	public SaResult checkBasic() {
		return SaResult.ok();
	}
	
}

When we access this interface, the browser will force a pop-up form:

When we enter the account password (sa / 123456), we can continue to access the data:

8. Service disabling verification

java复制代码@RestController
@RequestMapping("/at/")
public class AtController {

	// 只有当前服务没有禁用 comment 服务时,才能够进入方法  ---- http://localhost:8081/at/comment 
	@SaCheckDisable("comment")
	@RequestMapping("comment")
	public SaResult comment() {
		return SaResult.ok();
	}

}

The function of the @SaCheckDisable annotation is to detect whether the specified service is disabled for the current account. If it has been disabled, the specified method cannot be entered. In the following chapters, we will describe the code related to the service disabled in detail, so we can understand it here first.

9. Ignore authentication

Use @SaIgnore to indicate that an interface ignores authentication:

java复制代码@SaCheckLogin
@RestController
public class TestController {
	
	// ... 其它方法 
	
	// 此接口加上了 @SaIgnore 可以游客访问 
	@SaIgnore
	@RequestMapping("getList")
	public SaResult getList() {
		// ... 
		return SaResult.ok(); 
	}
}

The above code indicates that all methods in TestController can only be accessed after logging in, but the getList interface can be accessed by anonymous visitors.

  • When @SaIgnore modifies a method, it means that this method can be accessed by tourists, and when it modifies a class, it means that all interfaces in this class can be accessed by tourists.
  • @SaIgnore has the highest priority. When @SaIgnore appears together with other authentication annotations, other authentication annotations will be ignored.
  • @SaIgnore can also ignore the routing authentication in the Sa-Token interceptor, which we will talk about in the following [Routing Interception and Authentication] section.

10. Use annotation authentication in the business logic layer

Question: Can I write annotations in other architectural layers, such as the business logic layer?

Using the interceptor mode, annotation authentication can only be performed at the Controller layer. To use annotation authentication at any level, you can use the AOP annotation authentication plug-in.

xml复制代码<!-- Sa-Token 整合 SpringAOP 实现注解鉴权 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-aop</artifactId>
    <version>1.34.0</version>
</dependency>

After integrating this plug-in, you can use Sa-Token annotation authentication at any layer (such as business logic layer), but it should be noted that:

  • Interceptor mode and AOP mode cannot be integrated at the same time, otherwise a bug of annotation verification twice will occur in the Controller layer.

Guess you like

Origin blog.csdn.net/m0_71777195/article/details/130699181