diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/JurAuthController.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/JurAuthController.java new file mode 100644 index 00000000..d356e5c7 --- /dev/null +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/JurAuthController.java @@ -0,0 +1,112 @@ +package com.pj.cases; + +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.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 permissionList = StpUtil.getPermissionList(); + System.out.println("当前登录账号拥有的所有权限:" + permissionList); + + // 查询角色信息 ,如果当前会话未登录,会返回一个空集合 + List 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(); + } + +} diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/KickoutController.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/KickoutController.java new file mode 100644 index 00000000..f233970e --- /dev/null +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/KickoutController.java @@ -0,0 +1,59 @@ +package com.pj.cases; + +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("/kickout/") +public class KickoutController { + + /* + * 前提:首先调用登录接口进行登录,代码在 com.pj.cases.LoginAuthController 中有详细解释,此处不再赘述 + */ + + // 将指定账号强制注销 ---- http://localhost:8081/kickout/logout?userId=10001 + @RequestMapping("logout") + public SaResult logout(long userId) { + + // 强制注销等价于对方主动调用了注销方法,再次访问会提示:Token无效。 + StpUtil.logout(userId); + + // 返回 + return SaResult.ok(); + } + + // 将指定账号踢下线 ---- http://localhost:8081/kickout/kickout?userId=10001 + @RequestMapping("kickout") + public SaResult kickout(long userId) { + + // 踢人下线不会清除Token信息,而是将其打上特定标记,再次访问会提示:Token已被踢下线。 + StpUtil.kickout(userId); + + // 返回 + return SaResult.ok(); + } + + /* + * 你可以分别在强制注销和踢人下线后,再次访问一下登录校验接口,对比一下两者返回的提示信息有何不同 + * ---- http://localhost:8081/acc/checkLogin + */ + + // 根据 Token 值踢人 ---- http://localhost:8081/kickout/kickoutByTokenValue?tokenValue=xxxx-xxxx-xxxx-xxxx已登录账号的token值 + public SaResult kickoutByTokenValue(String tokenValue) { + + StpUtil.kickoutByTokenValue(tokenValue); + + // 返回 + return SaResult.ok(); + } + +} diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/LoginAuthController.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/LoginAuthController.java index e51be2a4..3c95178c 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/LoginAuthController.java +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/cases/LoginAuthController.java @@ -3,47 +3,137 @@ package com.pj.cases; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import cn.dev33.satoken.stp.SaTokenInfo; import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.util.SaResult; /** - * 登录认证示例 + * Sa-Token 登录认证示例 * * @author kong - * + * @since 2022-10-13 */ @RestController @RequestMapping("/acc/") public class LoginAuthController { - // 测试登录 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 + // 会话登录接口 ---- http://localhost:8081/acc/doLogin?name=zhang&pwd=123456 @RequestMapping("doLogin") public SaResult doLogin(String name, String pwd) { - // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对 + + // 第一步:比对前端提交的 账号名称 & 密码 是否正确,比对成功后开始登录 + // 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对 if("zhang".equals(name) && "123456".equals(pwd)) { + + // 第二步:根据账号id,进行登录 + // 此处填入的参数应该保持用户表唯一,比如用户id,不可以直接填入整个 User 对象 StpUtil.login(10001); + + // SaResult 是 Sa-Token 中对返回结果的简单封装,下面的示例将不再赘述 return SaResult.ok("登录成功"); } + return SaResult.error("登录失败"); } - // 查询登录状态 ---- http://localhost:8081/acc/isLogin + // 查询当前登录状态 ---- http://localhost:8081/acc/isLogin @RequestMapping("isLogin") public SaResult isLogin() { - return SaResult.ok("是否登录:" + StpUtil.isLogin()); + // StpUtil.isLogin() 查询当前客户端是否登录,返回 true 或 false + boolean isLogin = StpUtil.isLogin(); + return SaResult.ok("当前客户端是否登录:" + isLogin); + } + + // 校验当前登录状态 ---- http://localhost:8081/acc/checkLogin + @RequestMapping("checkLogin") + public SaResult checkLogin() { + // 检验当前会话是否已经登录, 如果未登录,则抛出异常:`NotLoginException` + StpUtil.checkLogin(); + + // 抛出异常后,代码将走入全局异常处理(GlobalException.java),如果没有抛出异常,则代表通过了登录校验,返回下面信息 + return SaResult.ok("校验登录成功,这行字符串是只有登录后才会返回的信息"); + } + + // 获取当前登录的账号是谁 ---- http://localhost:8081/acc/getLoginId + @RequestMapping("getLoginId") + public SaResult getLoginId() { + // 需要注意的是,StpUtil.getLoginId() 自带登录校验效果 + // 也就是说如果在未登录的情况下调用这句代码,框架就会抛出 `NotLoginException` 异常,效果和 StpUtil.checkLogin() 是一样的 + Object userId = StpUtil.getLoginId(); + System.out.println("当前登录的账号id是:" + userId); + + // 如果不希望 StpUtil.getLoginId() 触发登录校验效果,可以填入一个默认值 + // 如果会话未登录,则返回这个默认值,如果会话已登录,将正常返回登录的账号id + Object userId2 = StpUtil.getLoginId(0); + System.out.println("当前登录的账号id是:" + userId2); + + // 或者使其在未登录的时候返回 null + Object userId3 = StpUtil.getLoginIdDefaultNull(); + System.out.println("当前登录的账号id是:" + userId3); + + // 类型转换: + // StpUtil.getLoginId() 返回的是 Object 类型,你可以使用以下方法指定其返回的类型 + int userId4 = StpUtil.getLoginIdAsInt(); // 将返回值转换为 int 类型 + long userId5 = StpUtil.getLoginIdAsLong(); // 将返回值转换为 long 类型 + String userId6 = StpUtil.getLoginIdAsString(); // 将返回值转换为 String 类型 + + // 疑问:数据基本类型不是有八个吗,为什么只封装以上三种类型的转换? + // 因为大多数项目都是拿 int、long 或 String 声明 UserId 的类型的,实在没见过哪个项目用 double、float、boolean 之类来声明 UserId + System.out.println("当前登录的账号id是:" + userId4 + " --- " + userId5 + " --- " + userId6); + + // 返回给前端 + return SaResult.ok("当前客户端登录的账号id是:" + userId); } // 查询 Token 信息 ---- http://localhost:8081/acc/tokenInfo @RequestMapping("tokenInfo") public SaResult tokenInfo() { + // TokenName 是 Token 名称的意思,此值也决定了前端提交 Token 时应该使用的参数名称 + String tokenName = StpUtil.getTokenName(); + System.out.println("前端提交 Token 时应该使用的参数名称:" + tokenName); + + // 使用 StpUtil.getTokenValue() 获取前端提交的 Token 值 + // 框架默认前端可以从以下三个途径中提交 Token: + // Cookie (浏览器自动提交) + // Header头 (代码手动提交) + // Query 参数 (代码手动提交) 例如: /user/getInfo?satoken=xxxx-xxxx-xxxx-xxxx + // 读取顺序为: Query 参数 --> Header头 -- > Cookie + // 以上三个地方都读取不到 Token 信息的话,则视为前端没有提交 Token + String tokenValue = StpUtil.getTokenValue(); + System.out.println("前端提交的Token值为:" + tokenValue); + + // TokenInfo 包含了此 Token 的大多数信息 + SaTokenInfo info = StpUtil.getTokenInfo(); + System.out.println("Token 名称:" + info.getTokenName()); + System.out.println("Token 值:" + info.getTokenValue()); + System.out.println("当前是否登录:" + info.getIsLogin()); + System.out.println("当前登录的账号id:" + info.getLoginId()); + System.out.println("当前登录账号的类型:" + info.getLoginType()); + System.out.println("当前登录客户端的设备类型:" + info.getLoginDevice()); + System.out.println("当前 Token 的剩余有效期:" + info.getTokenTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在 + System.out.println("当前 Token 的剩余临时有效期:" + info.getTokenActivityTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在 + System.out.println("当前 User-Session 的剩余有效期" + info.getSessionTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在 + System.out.println("当前 Token-Session 的剩余有效期" + info.getTokenSessionTimeout()); // 单位:秒,-1代表永久有效,-2代表值不存在 + + // 返回给前端 return SaResult.data(StpUtil.getTokenInfo()); } - // 测试注销 ---- http://localhost:8081/acc/logout + // 会话注销 ---- http://localhost:8081/acc/logout @RequestMapping("logout") public SaResult logout() { + // 退出登录会清除三个地方的数据: + // 1、Redis中保存的 Token 信息 + // 2、当前请求上下文中保存的 Token 信息 + // 3、Cookie 中保存的 Token 信息(如果未使用Cookie模式则不会清除) StpUtil.logout(); - return SaResult.ok(); + + // StpUtil.logout() 在未登录时也是可以调用成功的, + // 也就是说,无论客户端有没有登录,执行完 StpUtil.logout() 后,都会处于未登录状态 + System.out.println("当前是否处于登录状态:" + StpUtil.isLogin()); + + // 返回给前端 + return SaResult.ok("退出登录成功"); } } diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java index 3c75d793..f907707d 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java @@ -3,6 +3,9 @@ package com.pj.current; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import cn.dev33.satoken.exception.NotLoginException; +import cn.dev33.satoken.exception.NotPermissionException; +import cn.dev33.satoken.exception.NotRoleException; import cn.dev33.satoken.util.SaResult; /** @@ -11,9 +14,9 @@ import cn.dev33.satoken.util.SaResult; @RestControllerAdvice public class GlobalException { - // 全局异常拦截 - @ExceptionHandler - public SaResult handlerException(Exception e) { + // 拦截:未登录异常 + @ExceptionHandler(NotLoginException.class) + public SaResult handlerException(NotLoginException e) { // 打印堆栈,以供调试 e.printStackTrace(); @@ -21,5 +24,26 @@ public class GlobalException { // 返回给前端 return SaResult.error(e.getMessage()); } + + // 拦截:缺少权限异常 + @ExceptionHandler(NotPermissionException.class) + public SaResult handlerException(NotPermissionException e) { + e.printStackTrace(); + return SaResult.error("缺少权限:" + e.getPermission()); + } + + // 拦截:缺少角色异常 + @ExceptionHandler(NotRoleException.class) + public SaResult handlerException(NotRoleException e) { + e.printStackTrace(); + return SaResult.error("缺少角色:" + e.getRole()); + } + + // 拦截:其它所有异常 + @ExceptionHandler(Exception.class) + public SaResult handlerException(Exception e) { + e.printStackTrace(); + return SaResult.error(e.getMessage()); + } } diff --git a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java index b6cc79f7..1c1e1e58 100644 --- a/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java +++ b/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java @@ -8,7 +8,10 @@ import org.springframework.stereotype.Component; import cn.dev33.satoken.stp.StpInterface; /** - * 自定义权限验证接口扩展 + * 自定义权限认证接口扩展,Sa-Token 将从此实现类获取每个账号拥有的权限码 + * + * @author kong + * @since 2022-10-13 */ @Component // 打开此注解,保证此类被springboot扫描,即可完成sa-token的自定义权限验证扩展 public class StpInterfaceImpl implements StpInterface { @@ -21,11 +24,11 @@ public class StpInterfaceImpl implements StpInterface { // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 List list = new ArrayList(); list.add("101"); - list.add("user-add"); - list.add("user-delete"); - list.add("user-update"); - list.add("user-get"); - list.add("article-get"); + list.add("user.add"); + list.add("user.update"); + list.add("user.get"); + // list.add("user.delete"); + list.add("art.*"); return list; } diff --git a/sa-token-doc/static/doc.css b/sa-token-doc/static/doc.css index 03065939..cc924ff2 100644 --- a/sa-token-doc/static/doc.css +++ b/sa-token-doc/static/doc.css @@ -242,7 +242,7 @@ body { /* 答题按钮 */ -#main .dt-btn{ +#main .dt-btn,#main .case-btn{ background-color: #e7ecf3; color: #385481; display: inline-block; @@ -250,20 +250,24 @@ body { border-radius: 1px; /* border-bottom-width: 0px !important; */ - /* background-color: #f0f9eb; - color: #42b983; - display: inline-block; - border: 1px #13ce66 solid; */ - margin-top: 10px; width: 100%; padding: 8px 14px; font-size: 14px; + transition: all 0.15s; /* 背景 */ background-image: url(icon/dati.svg); background-repeat: no-repeat; background-size: 20px 20px; - background-position: 1em 50%; + background-position: 1em 12px; text-indent: 2em; +} +/* 代码示例按钮 */ +#main .case-btn{ + background-color: #f4fdef; + color: #42b983; + border: 1px #c4e5b5 solid !important; + background-size: 18px 18px; + background-image: url(icon/code.svg); } \ No newline at end of file diff --git a/sa-token-doc/static/icon/code.svg b/sa-token-doc/static/icon/code.svg new file mode 100644 index 00000000..7f8d8c5a --- /dev/null +++ b/sa-token-doc/static/icon/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/sa-token-doc/use/jur-auth.md b/sa-token-doc/use/jur-auth.md index 16080dfd..e6e695e0 100644 --- a/sa-token-doc/use/jur-auth.md +++ b/sa-token-doc/use/jur-auth.md @@ -1,4 +1,10 @@ # 权限认证 + + + 本章代码示例:Sa-Token 权限认证 —— [ sa-token-demo-case:com.pj.cases.JurAuthController.java ] + + --- @@ -41,11 +47,11 @@ public class StpInterfaceImpl implements StpInterface { // 本list仅做模拟,实际项目中要根据具体业务逻辑来查询权限 List list = new ArrayList(); list.add("101"); - list.add("user-add"); - list.add("user-delete"); - list.add("user-update"); - list.add("user-get"); - list.add("article-get"); + list.add("user.add"); + list.add("user.update"); + list.add("user.get"); + // list.add("user.delete"); + list.add("art.*"); return list; } @@ -68,42 +74,42 @@ public class StpInterfaceImpl implements StpInterface { - loginId:账号id,即你在调用 `StpUtil.login(id)` 时写入的标识值。 - loginType:账号体系标识,此处可以暂时忽略,在 [ 多账户认证 ] 章节下会对这个概念做详细的解释。 -可参考代码:[码云:StpInterfaceImpl.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/satoken/StpInterfaceImpl.java) +可参考代码:[码云:StpInterfaceImpl.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/satoken/StpInterfaceImpl.java) -> 注意: StpInterface 接口在需要鉴权时由框架自动调用, 开发者只需要配置好就可以使用下面的鉴权方法或后面的注解鉴权 +> 注意: StpInterface 接口在需要鉴权时由框架自动调用,开发者只需要配置好就可以使用下面的鉴权方法或后面的注解鉴权 -### 权限认证 +### 权限校验 然后就可以用以下api来鉴权了 ``` java // 获取:当前账号所拥有的权限集合 StpUtil.getPermissionList(); -// 判断:当前账号是否含有指定权限, 返回true或false -StpUtil.hasPermission("user-update"); +// 判断:当前账号是否含有指定权限, 返回 true 或 false +StpUtil.hasPermission("user.add"); // 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException -StpUtil.checkPermission("user-update"); +StpUtil.checkPermission("user.add"); // 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过] -StpUtil.checkPermissionAnd("user-update", "user-delete"); +StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get"); // 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可] -StpUtil.checkPermissionOr("user-update", "user-delete"); +StpUtil.checkPermissionOr("user.add", "user.delete", "user.get"); ``` 扩展:`NotPermissionException` 对象可通过 `getLoginType()` 方法获取具体是哪个 `StpLogic` 抛出的异常 -### 角色认证 +### 角色校验 在Sa-Token中,角色和权限可以独立验证 ``` java // 获取:当前账号所拥有的角色集合 StpUtil.getRoleList(); -// 判断:当前账号是否拥有指定角色, 返回true或false +// 判断:当前账号是否拥有指定角色, 返回 true 或 false StpUtil.hasRole("super-admin"); // 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException @@ -137,22 +143,22 @@ public class GlobalExceptionHandler { } ``` -可参考:[码云:GlobalException.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-springboot/src/main/java/com/pj/current/GlobalException.java) +可参考:[码云:GlobalException.java](https://gitee.com/dromara/sa-token/blob/master/sa-token-demo/sa-token-demo-case/src/main/java/com/pj/current/GlobalException.java) ### 权限通配符 -Sa-Token允许你根据通配符指定**泛权限**,例如当一个账号拥有`user*`的权限时,`user-add`、`user-delete`、`user-update`都将匹配通过 +Sa-Token允许你根据通配符指定**泛权限**,例如当一个账号拥有`art.*`的权限时,`art.add`、`art.delete`、`art.update`都将匹配通过 ``` java -// 当拥有 user* 权限时 -StpUtil.hasPermission("user-add"); // true -StpUtil.hasPermission("user-update"); // true -StpUtil.hasPermission("art-add"); // false +// 当拥有 art.* 权限时 +StpUtil.hasPermission("art.add"); // true +StpUtil.hasPermission("art.update"); // true +StpUtil.hasPermission("goods.add"); // false -// 当拥有 *-delete 权限时 -StpUtil.hasPermission("user-add"); // false -StpUtil.hasPermission("user-delete"); // true -StpUtil.hasPermission("art-delete"); // true +// 当拥有 *.delete 权限时 +StpUtil.hasPermission("art.delete"); // true +StpUtil.hasPermission("user.delete"); // true +StpUtil.hasPermission("user.update"); // false // 当拥有 *.js 权限时 StpUtil.hasPermission("index.js"); // true @@ -174,9 +180,9 @@ StpUtil.hasPermission("index.html"); // false 2. 前端将权限码集合保存在`localStorage`或其它全局状态管理对象中。 3. 在需要权限控制的按钮上,使用 js 进行逻辑判断,例如在`Vue`框架中我们可以使用如下写法: ``` js - + ``` -其中:`arr`是当前用户拥有的权限码数组,`user:delete`是显示按钮需要拥有的权限码,`删除按钮`是用户拥有权限码才可以看到的内容。 +其中:`arr`是当前用户拥有的权限码数组,`user.delete`是显示按钮需要拥有的权限码,`删除按钮`是用户拥有权限码才可以看到的内容。 注意:以上写法只为提供一个参考示例,不同框架有不同写法,大家可根据项目技术栈灵活封装进行调用。 diff --git a/sa-token-doc/use/login-auth.md b/sa-token-doc/use/login-auth.md index 1473c00c..531d1eda 100644 --- a/sa-token-doc/use/login-auth.md +++ b/sa-token-doc/use/login-auth.md @@ -1,4 +1,10 @@ # 登录认证 + + + 本章代码示例:Sa-Token 登录认证 —— [ sa-token-demo-case:com.pj.cases.LoginAuthController.java ] + + --- @@ -16,7 +22,7 @@ 3. 用户后续的每次请求,都携带上这个 Token。 4. 服务器根据 Token 判断此会话是否登录成功。 -所谓登录认证,指的就是服务器校验账号密码,为用户颁发 Token 会话凭证的过程,这个 Token 也是我们后续通过接口校验的关键所在。 +所谓登录认证,指的就是服务器校验账号密码,为用户颁发 Token 会话凭证的过程,这个 Token 也是我们后续判断会话是否登录的关键所在。