前言:
现时同学们对“java用户权限框架”大致比较珍视,同学们都想要学习一些“java用户权限框架”的相关文章。那么小编同时在网摘上网罗了一些有关“java用户权限框架””的相关文章,希望你们能喜欢,大家一起来学习一下吧!Sa-Token简介
Sa-Token是一款轻量级的Java权限认证框架,可以用来解决登录认证、权限认证、Session会话、单点登录、OAuth2.0、微服务网关鉴权等一系列权限相关问题。
框架集成简单、开箱即用、API设计优雅,通过Sa-Token,你将以一种极其简单的方式实现系统的权限认证部分,有时候往往只需一行代码就能实现功能。
Sa-Token功能很全,具体可以参考下图。
使用
在SpringBoot中使用Sa-Token是非常简单的,接下来我们使用它来实现最常用的认证授权功能,包括登录认证、角色认证和权限认证。
集成及配置
Sa-Token的集成和配置都非常简单,不愧为开箱即用。
首先我们需要在项目的pom.xml中添加Sa-Token的相关依赖;
<!-- Sa-Token 权限认证 --><dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.24.0</version></dependency>复制代码然后在application.yml中添加Sa-Token的相关配置,考虑到要支持前后端分离项目,我们关闭从cookie中读取token,改为从head中读取token。
# Sa-Token配置sa-token: # token名称 (同时也是cookie名称) token-name: Authorization # token有效期,单位秒,-1代表永不过期 timeout: 2592000 # token临时有效期 (指定时间内无操作就视为token过期),单位秒 activity-timeout: -1 # 是否允许同一账号并发登录 (为false时新登录挤掉旧登录) is-concurrent: true # 在多人登录同一账号时,是否共用一个token (为false时每次登录新建一个token) is-share: false # token风格 token-style: uuid # 是否输出操作日志 is-log: false # 是否从cookie中读取token is-read-cookie: false # 是否从head中读取token is-read-head: true复制代码登录认证
在管理系统中,除了登录接口,基本都需要登录认证,在Sa-Token中使用路由拦截鉴权是最方便的,下面我们来实现下。
实现登录认证非常简单,首先在UmsAdminController中添加一个登录接口;
/** * 后台用户管理 * Created by macro on 2018/4/26. */@Controller@Api(tags = "UmsAdminController", description = "后台用户管理")@RequestMapping("/admin")public class UmsAdminController { @Autowired private UmsAdminService adminService; @ApiOperation(value = "登录以后返回token") @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public CommonResult login(@RequestParam String username, @RequestParam String password) { SaTokenInfo saTokenInfo = adminService.login(username, password); if (saTokenInfo == null) { return CommonResult.validateFailed("用户名或密码错误"); } Map<String, String> tokenMap = new HashMap<>(); tokenMap.put("token", saTokenInfo.getTokenValue()); tokenMap.put("tokenHead", saTokenInfo.getTokenName()); return CommonResult.success(tokenMap); }}复制代码然后在UmsAdminServiceImpl添加登录的具体逻辑,先验证密码,然后调用StpUtil.login(adminUser.getId())即可实现登录,调用API一行搞定;
/** * Created by macro on 2020/10/15. */@Slf4j@Servicepublic class UmsAdminServiceImpl implements UmsAdminService { @Override public SaTokenInfo login(String username, String password) { SaTokenInfo saTokenInfo = null; AdminUser adminUser = getAdminByUsername(username); if (adminUser == null) { return null; } if (!SaSecureUtil.md5(password).equals(adminUser.getPassword())) { return null; } // 密码校验成功后登录,一行代码实现登录 StpUtil.login(adminUser.getId()); // 获取当前登录用户Token信息 saTokenInfo = StpUtil.getTokenInfo(); return saTokenInfo; }}复制代码我们再添加一个测试接口用于查询当前登录状态,返回true表示已经登录;
/** * Created by macro on 2020/10/15. */@Slf4j@Servicepublic class UmsAdminServiceImpl implements UmsAdminService { @ApiOperation(value = "查询当前登录状态") @RequestMapping(value = "/isLogin", method = RequestMethod.GET) @ResponseBody public CommonResult isLogin() { return CommonResult.success(StpUtil.isLogin()); }}复制代码之后可以通过Swagger访问登录接口来获取Token了,使用账号为admin:123456,访问地址:然后在Authorization请求头中添加获取到的token;访问/admin/isLogin接口,data属性就会返回true了,表示你已经是登录状态了;接下来我们需要把除登录接口以外的接口都添加登录认证,添加Sa-Token的Java配置类SaTokenConfig,注册一个路由拦截器SaRouteInterceptor,这里我们的IgnoreUrlsConfig配置会从配置文件中读取白名单配置;
/** * Sa-Token相关配置 */@Configurationpublic class SaTokenConfig implements WebMvcConfigurer { @Autowired private IgnoreUrlsConfig ignoreUrlsConfig; /** * 注册sa-token拦截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> { // 获取配置文件中的白名单路径 List<String> ignoreUrls = ignoreUrlsConfig.getUrls(); // 登录认证:除白名单路径外均需要登录认证 SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin); })).addPathPatterns("/**"); }}复制代码application.yml文件中的白名单配置如下,注意开放Swagger的访问路径和静态资源路径;
# 访问白名单路径secure: ignored: urls: - / - /swagger-ui/ - /*.html - /favicon.ico - /**/*.html - /**/*.css - /**/*.js - /swagger-resources/** - /v2/api-docs/** - /actuator/** - /admin/login - /admin/isLogin复制代码由于未登录状态下访问接口,Sa-Token会抛出NotLoginException异常,所以我们需要全局处理下;
/** * 全局异常处理 * Created by macro on 2020/2/27. */@ControllerAdvicepublic class GlobalExceptionHandler { /** * 处理未登录的异常 */ @ResponseBody @ExceptionHandler(value = NotLoginException.class) public CommonResult handleNotLoginException(NotLoginException e) { return CommonResult.unauthorized(e.getMessage()); }}复制代码之后当我们在登录状态下访问接口时,可以获取到数据;当我们未登录状态(不带token)时无法正常访问接口,返回code为401。角色认证
角色认证也就是我们定义好一套规则,比如ROLE-ADMIN角色可以访问/brand下的所有资源,而ROLE_USER角色只能访问/brand/listAll,接下来我们来实现下角色认证。
首先我们需要扩展Sa-Token的StpInterface接口,通过实现方法来返回用户的角色码和权限码;
/** * 自定义权限验证接口扩展 */@Componentpublic class StpInterfaceImpl implements StpInterface { @Autowired private UmsAdminService adminService; @Override public List<String> getPermissionList(Object loginId, String loginType) { AdminUser adminUser = adminService.getAdminById(Convert.toLong(loginId)); return adminUser.getRole().getPermissionList(); } @Override public List<String> getRoleList(Object loginId, String loginType) { AdminUser adminUser = adminService.getAdminById(Convert.toLong(loginId)); return Collections.singletonList(adminUser.getRole().getName()); }}复制代码然后在Sa-Token的拦截器中配置路由规则,ROLE_ADMIN角色可以访问所有路径,而ROLE_USER只能访问/brand/listAll路径;
/** * Sa-Token相关配置 */@Configurationpublic class SaTokenConfig implements WebMvcConfigurer { @Autowired private IgnoreUrlsConfig ignoreUrlsConfig; /** * 注册sa-token拦截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> { // 获取配置文件中的白名单路径 List<String> ignoreUrls = ignoreUrlsConfig.getUrls(); // 登录认证:除白名单路径外均需要登录认证 SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin); // 角色认证:ROLE_ADMIN可以访问所有接口,ROLE_USER只能访问查询全部接口 SaRouter.match("/brand/listAll", () -> { StpUtil.checkRoleOr("ROLE_ADMIN","ROLE_USER"); //强制退出匹配链 SaRouter.stop(); }); SaRouter.match("/brand/**", () -> StpUtil.checkRole("ROLE_ADMIN")); })).addPathPatterns("/**"); }}复制代码当用户不是被允许的角色访问时,Sa-Token会抛出NotRoleException异常,我们可以全局处理下;
/** * 全局异常处理 * Created by macro on 2020/2/27. */@ControllerAdvicepublic class GlobalExceptionHandler { /** * 处理没有角色的异常 */ @ResponseBody @ExceptionHandler(value = NotRoleException.class) public CommonResult handleNotRoleException(NotRoleException e) { return CommonResult.forbidden(e.getMessage()); }}复制代码我们现在有两个用户,admin用户具有ROLE_ADMIN角色,macro用户具有ROLE_USER角色;使用admin账号访问/brand/list接口可以正常访问;使用macro账号访问/brand/list接口无法正常访问,返回code为403。权限认证
当我们给角色分配好权限,然后给用户分配好角色后,用户就拥有了这些权限。我们可以为每个接口分配不同的权限,拥有该权限的用户就可以访问该接口。这就是权限认证,接下来我们来实现下它。
我们可以在Sa-Token的拦截器中配置路由规则,admin用户可以访问所有路径,而macro用户只有读取的权限,没有写、改、删的权限;
/** * Sa-Token相关配置 */@Configurationpublic class SaTokenConfig implements WebMvcConfigurer { @Autowired private IgnoreUrlsConfig ignoreUrlsConfig; /** * 注册sa-token拦截器 */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> { // 获取配置文件中的白名单路径 List<String> ignoreUrls = ignoreUrlsConfig.getUrls(); // 登录认证:除白名单路径外均需要登录认证 SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin); // 权限认证:不同接口, 校验不同权限 SaRouter.match("/brand/listAll", () -> StpUtil.checkPermission("brand:read")); SaRouter.match("/brand/create", () -> StpUtil.checkPermission("brand:create")); SaRouter.match("/brand/update/{id}", () -> StpUtil.checkPermission("brand:update")); SaRouter.match("/brand/delete/{id}", () -> StpUtil.checkPermission("brand:delete")); SaRouter.match("/brand/list", () -> StpUtil.checkPermission("brand:read")); SaRouter.match("/brand/{id}", () -> StpUtil.checkPermission("brand:read")); })).addPathPatterns("/**"); }}复制代码当用户无权限访问时,Sa-Token会抛出NotPermissionException异常,我们可以全局处理下;
/** * 全局异常处理 * Created by macro on 2020/2/27. */@ControllerAdvicepublic class GlobalExceptionHandler { /** * 处理没有权限的异常 */ @ResponseBody @ExceptionHandler(value = NotPermissionException.class) public CommonResult handleNotPermissionException(NotPermissionException e) { return CommonResult.forbidden(e.getMessage()); }}复制代码使用admin账号访问/brand/delete接口可以正常访问;使用macro账号访问/brand/delete无法正常访问,返回code为403。总结
通过对Sa-Token的一波实践,我们可以发现它的API设计非常优雅,比起Shiro和Spring Security来说确实顺手多了。Sa-Token不仅提供了一系列强大的权限相关功能,还提供了很多标准的解决方案,比如Oauth2、分布式Session会话等,大家感兴趣的话可以研究下。
作者:MacroZheng
链接:
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
标签: #java用户权限框架 #java获取权限的包 #java oauth认证