最近看了好几个认证框架,什么 Appache Shiro 啦、Sa-Token 啦、Spring Security啦。。。尤其是Spring Security,做为对标 Spring Boot & Cloud 的框架 Solon 怎么的也要有自己的亲生安全认证框架。所以在适配了 Sa-Token(satoken-solon-plugin) 和 sureness(sureness-solon-plugin) 之后,也开发了Solon 的亲儿子:Solon Auth (solon.extend.auth)。设计目标是更加简单些、更直接些,同时为用户提供更丰富而不同的认证框架选择。

Solon Auth (solon.extend.auth)

Solon Auth 的定位是,只做认证控制。侧重对验证结果的适配,及在此基础上的统一控制和应用。功能会少,但适配起来不会晕。

Solon Auth 支持规则控制和注解控制两种方案,各有优缺点,也可组合使用:

  • 规则控制,适合在一个地方进行整体的宏观控制
  • 注解控制,方便在细节处精准把握

一、开始适配,完成2步动作即可

  • 第1步,构建一个认证适配器
@Configuration
public class Config {
@Bean
public AuthAdapter init() {
//
// 构建适配器
//
return new AuthAdapter()
.loginUrl("/login") //设定登录地址,未登录时自动跳转(如果不设定,则输出401错误)
.addRule(r -> r.include("**").verifyIp().failure((c, t) -> c.output("你的IP不在白名单"))) //添加规则
.addRule(b -> b.exclude("/login**").exclude("/run/**").verifyPath()) //添加规则
.processor(new AuthProcessorImpl()) //设定认证处理器
.failure((ctx, rst) -> { //设定默认的验证失败处理
ctx.render(rst);
});
}
} //规则配置说明
//1.include(path) 规则包函的路径范围,可多个
//2.exclude(path) 规则排序的路径池围,可多个
//3.failure(..) 规则失则后的处理
//4.verifyIp()... 规则要做的验证方案(可多个不同的验证方案)
  • 第2步,实现一个认证处理器

先了解一下 AuthProcessor 的接口,它对接的是一系列的验证动作结果。可能用户得自己也得多干点活,但很直观。

//认证处理器
public class AuthProcessorImpl implements AuthProcessor { @Override
public boolean verifyIp(String ip) {
//验证IP,是否有权访问
} @Override
public boolean verifyLogined() {
//验证登录状态,用户是否已登录
} @Override
public boolean verifyPath(String path, String method) {
//验证路径,用户可访问
} @Override
public boolean verifyPermissions(String[] permissions, Logical logical) {
//验证特定权限,用户是权有限
} @Override
public boolean verifyRoles(String[] roles, Logical logical) {
//验证特定角色,用户是否角色
}
}

现在做一次适配实战,用的是一份生产环境的代码:

public class AuthProcessorImpl implements AuthProcessor {
private int puid() {
return Context.current().session("puid", 0);
} @Override
public boolean verifyIp(String ip) {
return true; //ip不限制,直接返回true
} @Override
public boolean verifyLogined() {
return puid() > 0; //用户id大于0,说明已登录
} @Override
public boolean verifyPath(String path, String method) {
try {
if (BcfClient.hasUrlpath(path)) {
return BcfClient.hasUrlpathByUser(puid(), path);
} else {
return true;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} @Override
public boolean verifyPermissions(String[] permissions, Logical logical) {
int puid = puid(); try {
if (logical == Logical.AND) {
boolean isOk = true; for (String p : permissions) {
isOk = isOk && BcfClient.hasResourceByUser(puid, p);
} return isOk;
} else {
for (String p : permissions) {
if (BcfClient.hasResourceByUser(puid, p)) {
return true;
}
}
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
} @Override
public boolean verifyRoles(String[] roles, Logical logical) {
int puid = puid(); try {
if (logical == Logical.AND) {
boolean isOk = true; for (String p : roles) {
isOk = isOk && BcfClient.isUserInGroup(puid, p);
} return isOk;
} else {
for (String p : roles) {
if (BcfClient.isUserInGroup(puid, p)) {
return true;
}
}
return false;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

二、2种应用方式(一般组合使用)

刚才我们算是适配好了,现在就应用的活了。

  • 第1种,在 AuthAdapter 直接配置所有规则,或部分规则(也可以不配)
//参考上面的适配器 addRule(...)

配置的好处是,不需要侵入业务代码;同时在统一的地方,宏观可见;但容易忽略掉细节。

  • 第2种,基于注解做一部份(一般特定权限 或 特定角色时用)
@Mapping("/rock/agroup")
@Controller
public class AgroupController {
@Mapping("")
public void home() {
//agroup 首页
} @Mapping("inner")
public void inner() {
//内部列表页
} @AuthPermissions("agroup:edit") //需要特定权限
@Mapping("edit/{id}")
public void edit(int id) {
//编辑显示页,需要编辑权限
} @AuthRoles("admin") //需要特定角色
@Mapping("edit/{id}/ajax/save")
public void save(int id) {
//编辑处理接口,需要管理员权限
}
}

注解的好处是,微观可见,在一个方法上就可以看到它需要什么权限或角色,不容易忽略。

  • 组合使用方式

一般,用配置规则,控制所有需要登录的地址;用注解,控制特定的权限或角色。

三、本案源码

https://gitee.com/noear/solon_demo/tree/master/demo16.solon_auth

四、其它生产项目应用

https://gitee.com/noear/water/tree/master/wateradmin

https://gitee.com/noear/sponge/tree/main/spongeadmin

附:Solon 项目地址

附:Solon 其它入门示例

最新文章

  1. 使用phar上线你的代码包
  2. REST API 安全设计指南
  3. Activiti 流程实例、任务、执行对象及相关的表
  4. MyDiary,《你的名字。》同款日记应用
  5. SVN提交提示:working copy is not up-to-date解决方法
  6. mysql insert一条记录后怎样返回创建记录的主键id,last_insert_id(),selectkey
  7. malloc/free 和 new/delete 的区别
  8. 解决方案--java执行cmd命令ProcessBuilder--出错Exception in thread "main" java.io.IOException: Cannot run program "dir d:\": CreateProcess error=2(xjl456852原创)
  9. ResultSet取结果集多少条记录方法及分页概要
  10. HRBUST 1909 理工门外的树(双数组实现线段树功能)
  11. java 字符串大小比较
  12. web前端工程师全套教程免费分享
  13. Nginx集群之WCF分布式消息队列
  14. docker(3)容器管理命令
  15. 一个http请求从用户输入网址开始到结束都发生了什么
  16. Oracle 的ORION工具简单使用
  17. spoj694
  18. 走进java
  19. window 系统显示svg、psd格式文件
  20. PHP开发者的路书

热门文章

  1. Xposed学习二:实现机制
  2. CVE-2011-0104:Microsoft Office Excel 栈溢出漏洞修复分析
  3. Windows PE变形练手1-用PE自己的机器码修改自己的逻辑
  4. 神经网络与机器学习 笔记—LMS(最小均方算法)和学习率退火
  5. .NET之默认依赖注入
  6. vue的快速入门【IDEA版本】
  7. ThinkPHP5 Apache / IIs环境下 URL重写
  8. window 10 删除文件夹需要管理员权限
  9. java如何调用本地扬声器
  10. Windows服务与会话的理解