いわゆる権限認証、コア ロジックは、アカウントが指定された権限を持っているかどうかを判断することです:
そうであれば、あなたは、通過が許可されます。 ############いいえ?それではアクセス禁止です!
基礎となるデータを詳しく調べると、各アカウントには一連の権限コードがあり、フレームワークはこのセットに指定された権限コードが含まれているかどうかを確認します。
が設定されている場合、権限を確認します
"user-update"、結果は次のようになります: 検証に失敗しました。
へのアクセスは禁止されています。 それでは、問題の核心は次のとおりです:
アカウントが所有する許可コードのセットを取得するにはどうすればよいでしょうか?
この操作ではどの権限コードを確認する必要がありますか?
次に、Sa-Token を使用して SpringBoot で権限認証操作を完了する方法を紹介します。
まず、Sa-Token 依存関係をプロジェクトに導入します:SpringBoot 3.x注:<!-- Sa-Token 权限认证 --> <dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.34.0</version> </dependency>ログイン後にコピー
を使用している場合は、## を追加するだけです。 #sa -token-spring-boot-starter
はsa-token-spring-boot3-starter に変更できます。
2. 現在のアカウント権限コード セットを取得します
各プロジェクトには異なるニーズがあり、権限の設計も常に変化しているため、[現在のアカウント権限コード セットを取得する] は構築できませんSa-Token はこの操作をインターフェイスの形式で公開するため、独自のビジネス ロジックに従って書き換えることができます。
/** * 自定义权限验证接口扩展 */ @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; } }
パラメータの説明:
loginId: アカウント ID。StpUtil.login(id)
を呼び出すときに書き込む識別値です。loginType: アカウント システム識別子、ここでは一時的に無視できます。この概念については、[複数アカウント認証] の章で詳しく説明します。
注: コンポーネントが Springboot によってスキャンされ、Sa-Token に正常に挿入されるようにするには、
クラスに3. 権限の検証スタートアップ クラス:
@SpringBootApplication public class SaTokenCaseApplication { public static void main(String[] args) { SpringApplication.run(SaTokenCaseApplication.class, args); System.out.println("\n启动成功:Sa-Token配置如下:" + SaManager.getConfig()); } }
// 获取:当前账号所拥有的权限集合 StpUtil.getPermissionList(); // 判断:当前账号是否含有指定权限, 返回 true 或 false StpUtil.hasPermission("user.add"); // 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException StpUtil.checkPermission("user.add"); // 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过] StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get"); // 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");
NotPermissionException
オブジェクトは、getLoginType()
メソッド4 を通じて
StpLogic がスローされる特定の例外を取得できます。 ロールの検証
In Sa -Inトークン、ロール、権限は個別に検証できます
// 获取:当前账号所拥有的角色集合 StpUtil.getRoleList(); // 判断:当前账号是否拥有指定角色, 返回 true 或 false StpUtil.hasRole("super-admin"); // 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException StpUtil.checkRole("super-admin"); // 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过] StpUtil.checkRoleAnd("super-admin", "shop-admin"); // 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] StpUtil.checkRoleOr("super-admin", "shop-admin");
getLoginType()
メソッドを通じて取得できますStpLogic スロー例外
5. グローバル例外のインターセプト
学生の中には、認証が失敗して例外がスローされた場合はどうなるのか、と尋ねたい人もいます。ユーザーに例外を表示しますか? ###もちろん違います!
@RestControllerAdvice public class GlobalExceptionHandler { // 全局异常拦截 @ExceptionHandler public SaResult handlerException(Exception e) { e.printStackTrace(); return SaResult.error(e.getMessage()); } }
6. 許可ワイルドカードSa-Token を使用すると、次のことが可能になります。ワイルドカードに
general 権限を指定します。たとえば、アカウントに
art.*、art.delete## の権限がある場合です。 #, art.update は、
// 当拥有 art.* 权限时 StpUtil.hasPermission("art.add"); // true StpUtil.hasPermission("art.update"); // true StpUtil.hasPermission("goods.add"); // false // 当拥有 *.delete 权限时 StpUtil.hasPermission("art.delete"); // true StpUtil.hasPermission("user.delete"); // true StpUtil.hasPermission("user.update"); // false // 当拥有 *.js 权限时 StpUtil.hasPermission("index.js"); // true StpUtil.hasPermission("index.css"); // false StpUtil.hasPermission("index.html"); // false
God 権限によって照合されます。アカウントに "*"
権限がある場合、アカウントは任意の権限コードを通じて認証できます。 (ロールは認証でも同じ)
7. 権限をボタン レベルまで正確に設定するにはどうすればよいですか? アイデア: このような正確な範囲制御は、バックエンドのみに依存して実現するのは難しく、このとき、フロントエンドは一定の論理的判断を行う必要があります。 フロントエンドとバックエンドが統合されたプロジェクトの場合は、Thymeleaf タグ方言を参照できます。フロントエンドとバックエンドが分離されたプロジェクトの場合は、ボタン レベルまで正確な権限とは、
権限スコープはページ上の各ボタンに
を表示するかどうかを制御できることを意味します。
ログインすると、現在のアカウントのすべての権限コードが一度にフロントエンドに返されます。 フロントエンドは、権限コード コレクションを
Vue フレームワークでは、次のような記述が使用できます。
##
<button v-if="arr.indexOf('user.delete') > -1">删除按钮</button>
user.delete はボタンを表示するために必要な権限コード、
削除ボタン
8. フロントエンドに認証がある場合、バックエンドにも認証が必要ですか? #########必要!
<p>前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证服务器安全,无论前端是否进行了权限校验,后端接口都需要对会话请求再次进行权限校验!</p><h3>九、来个小示例,加深一下印象</h3><p>新建 <code>JurAuthController
,复制以下代码
package com.pj.cases.use; import java.util.List; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; /** * Sa-Token 权限认证示例 * * @author kong * @since 2022-10-13 */ @RestController @RequestMapping("/jur/") public class JurAuthController { /* * 前提1:首先调用登录接口进行登录,代码在 com.pj.cases.use.LoginAuthController 中有详细解释,此处不再赘述 * ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 * * 前提2:项目实现 StpInterface 接口,代码在 com.pj.satoken.StpInterfaceImpl * Sa-Token 将从此实现类获取 每个账号拥有哪些权限。 * * 然后我们就可以使用以下示例中的代码进行鉴权了 */ // 查询权限 ---- http://localhost:8081/jur/getPermission @RequestMapping("getPermission") public SaResult getPermission() { // 查询权限信息 ,如果当前会话未登录,会返回一个空集合 List<String> permissionList = StpUtil.getPermissionList(); System.out.println("当前登录账号拥有的所有权限:" + permissionList); // 查询角色信息 ,如果当前会话未登录,会返回一个空集合 List<String> roleList = StpUtil.getRoleList(); System.out.println("当前登录账号拥有的所有角色:" + roleList); // 返回给前端 return SaResult.ok() .set("roleList", roleList) .set("permissionList", permissionList); } // 权限校验 ---- http://localhost:8081/jur/checkPermission @RequestMapping("checkPermission") public SaResult checkPermission() { // 判断:当前账号是否拥有一个权限,返回 true 或 false // 如果当前账号未登录,则永远返回 false StpUtil.hasPermission("user.add"); StpUtil.hasPermissionAnd("user.add", "user.delete", "user.get"); // 指定多个,必须全部拥有才会返回 true StpUtil.hasPermissionOr("user.add", "user.delete", "user.get"); // 指定多个,只要拥有一个就会返回 true // 校验:当前账号是否拥有一个权限,校验不通过时会抛出 `NotPermissionException` 异常 // 如果当前账号未登录,则永远校验失败 StpUtil.checkPermission("user.add"); StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get"); // 指定多个,必须全部拥有才会校验通过 StpUtil.checkPermissionOr("user.add", "user.delete", "user.get"); // 指定多个,只要拥有一个就会校验通过 return SaResult.ok(); } // 角色校验 ---- http://localhost:8081/jur/checkRole @RequestMapping("checkRole") public SaResult checkRole() { // 判断:当前账号是否拥有一个角色,返回 true 或 false // 如果当前账号未登录,则永远返回 false StpUtil.hasRole("admin"); StpUtil.hasRoleAnd("admin", "ceo", "cfo"); // 指定多个,必须全部拥有才会返回 true StpUtil.hasRoleOr("admin", "ceo", "cfo"); // 指定多个,只要拥有一个就会返回 true // 校验:当前账号是否拥有一个角色,校验不通过时会抛出 `NotRoleException` 异常 // 如果当前账号未登录,则永远校验失败 StpUtil.checkRole("admin"); StpUtil.checkRoleAnd("admin", "ceo", "cfo"); // 指定多个,必须全部拥有才会校验通过 StpUtil.checkRoleOr("admin", "ceo", "cfo"); // 指定多个,只要拥有一个就会校验通过 return SaResult.ok(); } // 权限通配符 ---- http://localhost:8081/jur/wildcardPermission @RequestMapping("wildcardPermission") public SaResult wildcardPermission() { // 前提条件:在 StpInterface 实现类中,为账号返回了 "art.*" 泛权限 StpUtil.hasPermission("art.add"); // 返回 true StpUtil.hasPermission("art.delete"); // 返回 true StpUtil.hasPermission("goods.add"); // 返回 false,因为前缀不符合 // * 符合可以出现在任意位置,比如权限码的开头,当账号拥有 "*.delete" 时 StpUtil.hasPermission("goods.add"); // false StpUtil.hasPermission("goods.delete"); // true StpUtil.hasPermission("art.delete"); // true // 也可以出现在权限码的中间,比如当账号拥有 "shop.*.user" 时 StpUtil.hasPermission("shop.add.user"); // true StpUtil.hasPermission("shop.delete.user"); // true StpUtil.hasPermission("shop.delete.goods"); // false,因为后缀不符合 // 注意点: // 1、上帝权限:当一个账号拥有 "*" 权限时,他可以验证通过任何权限码 // 2、角色校验也可以加 * ,指定泛角色,例如: "*.admin",暂不赘述 return SaResult.ok(); } }
代码注释已针对每一步操作做出详细解释,大家可根据可参照注释中的访问链接进行逐步测试。
以上がSpringBoot が Sa-Token を使用してパーミッション認証を実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。