Sa-Token一款功能强大的权限认证框架,用起来够优雅

imToken 是一款全球领先的区块链数字资产管理工具[ZB],帮助你安全管理BTC, ETH, ATOM, EOS, TRX, CKB, BCH, LTC, DOT, KSM, FIL, XTZ 资产,同时支持去中心化币币兑换功能 ...

在管理系统中,除了登录接口imToken官网,基本都需要登录认证,在Sa-Token中使用路由拦截鉴权是最方便的,下面我们来实现下。

Sa-Token路由拦截鉴权

/**
 * 后台用户管理
 * 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 tokenMap = new HashMap<>();
        tokenMap.put("token", saTokenInfo.getTokenValue());
        tokenMap.put("tokenHead", saTokenInfo.getTokenName());
        return CommonResult.success(tokenMap);
    }
}

Sa-Token角色认证实现

/**
 * Created by macro on 2020/10/15.
 */
@Slf4j
@Service
public 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;
    }
}

Sa-Token权限认证接口

/**
 * Created by macro on 2020/10/15.
 */
@Slf4j
@Service
public class UmsAdminServiceImpl implements UmsAdminService {
    @ApiOperation(value = "查询当前登录状态")
    @RequestMapping(value = "/isLogin", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult isLogin() {
        return CommonResult.success(StpUtil.isLogin());
    }
}

Sa-Token角色认证实现_Sa-Token路由拦截鉴权_token 权限管理·(中国)官方网站

Sa-Token路由拦截鉴权_token 权限管理·(中国)官方网站_Sa-Token角色认证实现

Sa-Token路由拦截鉴权_Sa-Token角色认证实现_token 权限管理·(中国)官方网站

/**
 * Sa-Token相关配置
 */
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    /**
     * 注册sa-token拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> {
            // 获取配置文件中的白名单路径
            List ignoreUrls = ignoreUrlsConfig.getUrls();
            // 登录认证:除白名单路径外均需要登录认证
            SaRouter.match(Collections.singletonList("/**"), ignoreUrls, StpUtil::checkLogin);
        })).addPathPatterns("/**");
    }
}

# 访问白名单路径
secure:
  ignored:
    urls:
      - /
      - /swagger-ui/
      - /*.html
      - /favicon.ico
      - /**/*.html
      - /**/*.css
      - /**/*.js
      - /swagger-resources/**
      - /v2/api-docs/**
      - /actuator/**
      - /admin/login
      - /admin/isLogin

/**
 * 全局异常处理
 * Created by macro on 2020/2/27.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理未登录的异常
     */
    @ResponseBody
    @ExceptionHandler(value = NotLoginException.class)
    public CommonResult handleNotLoginException(NotLoginException e) {
        return CommonResult.unauthorized(e.getMessage());
    }
}

token 权限管理·(中国)官方网站_Sa-Token路由拦截鉴权_Sa-Token角色认证实现

Sa-Token角色认证实现_Sa-Token路由拦截鉴权_token 权限管理·(中国)官方网站

角色认证

角色认证也就是我们定义好一套规则,比如ROLE-ADMIN角色可以访问/brand下的所有资源,而角色只能访问/brand/,接下来我们来实现下角色认证。

/**
 * 自定义权限验证接口扩展
 */
@Component
public class StpInterfaceImpl implements StpInterface {
    @Autowired
    private UmsAdminService adminService;
    @Override
    public List getPermissionList(Object loginId, String loginType) {
        AdminUser adminUser = adminService.getAdminById(Convert.toLong(loginId));
        return adminUser.getRole().getPermissionList();
    }
    @Override
    public List getRoleList(Object loginId, String loginType) {
        AdminUser adminUser = adminService.getAdminById(Convert.toLong(loginId));
        return Collections.singletonList(adminUser.getRole().getName());
    }
}

/**
 * Sa-Token相关配置
 */
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    /**
     * 注册sa-token拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> {
            // 获取配置文件中的白名单路径
            List 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("/**");
    }
}

/**
 * 全局异常处理
 * Created by macro on 2020/2/27.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理没有角色的异常
     */
    @ResponseBody
    @ExceptionHandler(value = NotRoleException.class)
    public CommonResult handleNotRoleException(NotRoleException e) {
        return CommonResult.forbidden(e.getMessage());
    }
}

Sa-Token路由拦截鉴权_Sa-Token角色认证实现_token 权限管理·(中国)官方网站

Sa-Token角色认证实现_token 权限管理·(中国)官方网站_Sa-Token路由拦截鉴权

Sa-Token路由拦截鉴权_token 权限管理·(中国)官方网站_Sa-Token角色认证实现

权限认证

当我们给角色分配好权限,然后给用户分配好角色后,用户就拥有了这些权限。我们可以为每个接口分配不同的权限,拥有该权限的用户就可以访问该接口。这就是权限认证,接下来我们来实现下它。

/**
 * Sa-Token相关配置
 */
@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
    @Autowired
    private IgnoreUrlsConfig ignoreUrlsConfig;
    /**
     * 注册sa-token拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaRouteInterceptor((req, resp, handler) -> {
            // 获取配置文件中的白名单路径
            List 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("/**");
    }
}

/**
 * 全局异常处理
 * Created by macro on 2020/2/27.
 */
@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 处理没有权限的异常
     */
    @ResponseBody
    @ExceptionHandler(value = NotPermissionException.class)
    public CommonResult handleNotPermissionException(NotPermissionException e) {
        return CommonResult.forbidden(e.getMessage());
    }
}

Sa-Token角色认证实现_token 权限管理·(中国)官方网站_Sa-Token路由拦截鉴权

Sa-Token角色认证实现_Sa-Token路由拦截鉴权_token 权限管理·(中国)官方网站

总结

通过对Sa-Token的一波实践,我们可以发现它的API设计非常优雅,比起Shiro和 来说确实顺手多了。Sa-Token不仅提供了一系列强大的权限相关功能,还提供了很多标准的解决方案,比如、分布式会话等,大家感兴趣的话可以研究下。

参考资料

Sa-Token的官方文档很全,也很良心,不仅提供了解决方式,还提供了解决思路token 权限管理·(中国)官方网站,强烈建议大家去看下。

token 权限管理·(中国)官方网站_Sa-Token路由拦截鉴权_Sa-Token角色认证实现

官方文档:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

返回顶部
跳到底部

Copyright © 2002-2024 imToken钱包下载官网 Rights Reserved.
备案号:晋ICP备13003952号

谷歌地图 | 百度地图
Powered by Z-BlogPHP Theme By open开发