深入解析 Apache Shiro 授权认证体系原理,解决开发难题
ccwgpt 2025-05-08 17:09 17 浏览 0 评论
你在做互联网后端开发的时候,有没有遇到过这样的情况:用户登录系统后,不同用户对各种功能模块的访问权限管理起来特别麻烦。有的功能普通用户不能访问,只有管理员可以,可怎么准确无误地实现这种权限控制呢?这其实就是授权认证体系要解决的关键问题,而 Apache Shiro 在这方面堪称一把利器。
Apache Shiro介绍
Apache Shiro 是一个强大且易用的 Java 安全框架,它提供了身份验证、授权、加密和会话管理等功能。在众多互联网项目中,随着业务复杂度增加,对用户权限的精细化管理需求越来越高。传统的自己编写简单的权限控制代码,不仅容易出错,而且扩展性差。Apache Shiro 的出现,就是为了给开发者提供一套全面且易于集成的安全解决方案。它可以轻松集成到各种 Java Web 应用、企业级应用中,让开发者专注于业务逻辑,而不必在底层的安全认证和授权机制上耗费过多精力。
认证流程
当用户在前端输入用户名和密码登录时,这些信息会被封装成一个AuthenticationToken传递到后端。常见的AuthenticationToken实现类如UsernamePasswordToken,它携带了用户名和密码信息。在后端,Shiro 的Subject代表当前执行操作的用户,它调用login方法,将AuthenticationToken交给SecurityManager。
从源码角度来看,Subject的login方法实际会调用SecurityManager的login方法。在SecurityManager类中,关键代码如下:
public Subject login(Subject subject, AuthenticationToken token) throws AuthenticationException {
// 这里开始认证流程
AuthenticationInfo info = authenticate(token);
Subject loggedIn = createSubject(token, info, subject);
onSuccessfulLogin(token, info, loggedIn);
return loggedIn;
}
SecurityManager会委托配置好的Realm去验证用户身份。Realm就像是一个数据仓库,它从数据库或者其他数据源中获取用户的真实身份信息和密码等凭证。比如,如果用户名为 “admin”,Realm会去数据库中查询 “admin” 对应的密码。在实际应用中,为了保证安全性,密码通常不会以明文形式存储,而是经过加密处理,如使用 SHA - 256 等加密算法。
自定义Realm时,通常会继承AuthorizingRealm抽象类,并重写doGetAuthenticationInfo方法,示例代码如下:
public class CustomRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 授权相关逻辑,这里先不展开
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
// 从数据库查询用户信息,这里假设使用JDBC
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DriverManager.getConnection(url, username, password);
String sql = "SELECT password FROM users WHERE username =?";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
rs = ps.executeQuery();
if (rs.next()) {
String encryptedPassword = rs.getString("password");
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
username, encryptedPassword, getName());
return info;
} else {
throw new UnknownAccountException("用户不存在");
}
} catch (SQLException e) {
e.printStackTrace();
throw new AuthenticationException("数据库查询异常");
} finally {
// 关闭资源
try {
if (rs!= null) rs.close();
if (ps!= null) ps.close();
if (conn!= null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
Realm从数据库中获取到加密后的密码,然后将前端传来的密码也按照相同的加密算法进行加密,再比对两者是否一致。如果一致,认证就通过了。
在这个过程中,还可能涉及到一些额外的验证环节,例如多因素认证。假设系统开启了短信验证码功能,当用户输入用户名和密码后,Realm在验证密码的同时,还会检查用户输入的短信验证码是否正确,只有两者都匹配,认证才会通过。这时候可以在doGetAuthenticationInfo方法中添加对短信验证码的验证逻辑。
授权流程
用户认证通过后,就涉及到授权。比如,普通用户不能访问系统的用户管理模块,只有管理员可以。Shiro 的SecurityManager会根据用户的身份信息,从Realm中获取用户所拥有的角色和权限信息。
在 Shiro 中,权限的定义非常灵活,可以是简单的字符串表示,如 “user:manage” 表示对用户管理功能的操作权限,也可以是更复杂的基于资源和操作的权限描述。例如,“document:read:123” 表示对编号为 123 的文档有读取权限。
从源码层面分析,当判断用户是否具有某个权限时,会调用SecurityManager的isPermitted方法,该方法最终会委托给Authorizer进行权限判断。在AuthorizingRealm类中,与授权相关的关键方法是doGetAuthorizationInfo,当需要判断用户权限时会调用此方法来获取用户的角色和权限信息。
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
// 从数据库查询用户角色和权限,这里假设使用JDBC
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
try {
conn = DriverManager.getConnection(url, username, password);
// 查询用户角色
String roleSql = "SELECT role_name FROM user_roles WHERE username =?";
ps = conn.prepareStatement(roleSql);
ps.setString(1, username);
rs = ps.executeQuery();
List<String> roleList = new ArrayList<>();
while (rs.next()) {
String role = rs.getString("role_name");
roleList.add(role);
}
info.setRoles(new HashSet<>(roleList));
// 查询用户权限
String permissionSql = "SELECT permission FROM role_permissions WHERE role_name IN (";
for (int i = 0; i < roleList.size(); i++) {
if (i > 0) {
permissionSql += ", ";
}
permissionSql += "?";
}
permissionSql += ")";
ps = conn.prepareStatement(permissionSql);
for (int i = 0; i < roleList.size(); i++) {
ps.setString(i + 1, roleList.get(i));
}
rs = ps.executeQuery();
List<String> permissionList = new ArrayList<>();
while (rs.next()) {
String permission = rs.getString("permission");
permissionList.add(permission);
}
info.setStringPermissions(new HashSet<>(permissionList));
return info;
} catch (SQLException e) {
e.printStackTrace();
throw new AuthorizationException("数据库查询异常");
} finally {
// 关闭资源
try {
if (rs!= null) rs.close();
if (ps!= null) ps.close();
if (conn!= null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Realm从数据库或者其他数据源中获取用户对应的角色和权限信息。数据库表结构通常会设计用户表、角色表、用户角色关联表以及权限表、角色权限关联表。当用户尝试访问某个功能时,Shiro 会检查该用户是否具有相应的权限。比如用户尝试访问用户管理页面,Shiro 会从Realm获取该用户的权限列表,判断其中是否包含 “user:manage” 权限,如果没有,就会阻止访问,并返回权限不足的提示。
而且,Shiro 还支持权限继承和组合。比如,一个高级管理员角色可能继承了普通管理员角色的所有权限,同时还拥有一些额外的权限。在进行权限检查时,Shiro 会递归地检查用户所拥有的角色及其继承角色的所有权限,确保授权判断的准确性。在Authorizer的实现类中,会有相应的逻辑来处理权限继承和组合的情况,这里不再详细展开源码分析。
总结
Apache Shiro 的授权认证体系原理虽然看起来有些复杂,但一旦理解并应用到项目中,会极大地提升系统的安全性和可维护性。各位后端开发的伙伴们,不妨在自己的下一个项目中尝试引入 Apache Shiro,体验它带来的便捷。如果你在使用过程中有任何问题或者心得,欢迎在评论区留言分享,让我们一起在开发的道路上不断进步。
相关推荐
- 2025南通中考作文解读之四:结构框架
-
文题《继续走,迈向远方》结构框架:清晰叙事,层层递进示例结构:1.开头(点题):用环境描写或比喻引出“走”与“远方”,如“人生如一条长路,每一次驻足后,都需要继续走,才能看见更美的风景”。2.中间...
- 高中数学的知识框架(高中数学知识框架图第三章)
-
高中数学的知识框架可以划分为多个核心板块,每个板块包含具体的知识点与内容,以下为详细的知识框架结构:基础知识1.集合与逻辑用语:涵盖集合的概念、表示方式、性质、运算,以及命题、四种命题关系、充分条件...
- 决定人生的六大框架(决定人生的要素)
-
45岁的自己混到今天,其实是失败的,要是早点意识到影响人生的六大框架,也不至于今天的模样啊!排第一的是环境,不是有句话叫人是环境的产物,身边的环境包括身边的人和事,这些都会对一个人产生深远的影响。其次...
- 2023年想考过一级造价师土建计量,看这30个知识点(三)
-
第二章工程构造考点一:工业建筑分类[考频分析]★★★1.按厂房层数分:(1)单层厂房;(2)多层厂房;(3)混合层数厂房。2.按工业建筑用途分:(1)生产厂房;(2)生产辅助厂房;(3)动力用厂房;(...
- 一级建造师习题集-建筑工程实务(第一章-第二节-2)
-
建筑工程管理与实务题库(章节练习)第一章建筑工程技术第二节结构设计与构造二、结构设计1.常见建筑结构体系中,适用建筑高度最小的是()。A.框架结构体系B.剪力墙结构体系C.框架-剪力墙结构体系D...
- 冷眼读书丨多塔斜拉桥,这么美又这么牛
-
”重大交通基础设施的建设是国民经济和社会发展的先导,是交通运输行业新技术集中应用与创新的综合体现。多塔斜拉桥因跨越能力强、地形适应性强、造型优美等特点,备受桥梁设计者的青睐,在未来跨越海峡工程中将得...
- 2021一级造价师土建计量知识点:民用建筑分类
-
2021造价考试备考开始了,学霸君为大家整理了一级造价师备考所用的知识点,希望对大家的备考道路上有所帮助。 民用建筑分类 一、按层数和高度分 1.住宅建筑按层数分类:1~3层为低层住宅,4~6层...
- 6个建筑结构常见类型,你都知道吗?
-
建筑结构是建筑物中支承荷载(作用)起骨架作用的体系。结构是由构件组成的。构件有拉(压)杆、梁、板、柱、拱、壳、薄膜、索、基础等。常见的建筑结构类型有6种:砖混结构、砖木结构、框架结构、钢筋混凝土结构、...
- 框架结构设计经验总结(框架结构设计应注意哪些问题)
-
1.结构设计说明主要是设计依据,抗震等级,人防等级,地基情况及承载力,防潮抗渗做法,活荷载值,材料等级,施工中的注意事项,选用详图,通用详图或节点,以及在施工图中未画出而通过说明来表达的信息。2.各...
- 浅谈混凝土框架结构设计(混凝土框架结构设计主要内容)
-
浅谈混凝土框架结构设计 摘要:结构设计是个系统的全面的工作,需要扎实的理论知识功底,灵活创新的思维和严肃认真负责的工作态度。钢筋混凝土框架结构虽然相对简单,但设计中仍有很多需要注意的问题。本文针...
- 2022一级建造师《建筑实务》1A412020 结构设计 精细考点整理
-
历年真题分布统计1A412021常用建筑结构体系和应用一、混合结构体系【2012-3】指楼盖和屋盖采用钢筋混凝土或钢木结构,而墙和柱采用砌体结构建造的房屋,大多用在住宅、办公楼、教学楼建筑中。优点:...
- 破土动工!这个故宫“分院”科技含量有点儿高
-
故宫“分院”设计图。受访者供图近日,位于北京海淀区西北旺镇的故宫北院区项目已开始破土动工,该项目也被称作故宫“分院”,筹备近十年之久。据悉,故宫本院每年展览文物的数量不到1万件,但是“分院”建成后,预...
- 装配式结构体系介绍(上)(装配式结构如何设计)
-
PC构件深化、构件之间连接节点做法等与相应装配式结构体系密切相关。本节列举目前常见的几种装配式结构体系:装配整体式混凝土剪力墙结构体系、装配整体式混凝土框架结构体系、装配整体式混凝土空腔结构体系(S...
- 这些不是双向抗侧结构体系(这些不是双向抗侧结构体系的特点)
-
双向抗侧土木吧规范对双向抗恻力结构有何规定?为何不应采用单向有墙的结构?双向抗侧土木吧1.规范对双向抗侧力结构体系的要求抗侧力体系是指抵抗水平地震作用及风荷载的结构体系。对于结构体系的布置,规范针对...
- 2022一级建造师《建筑实务》1A412020 结构设计 精细化考点整理
-
1A412021常用建筑结构体系和应用一、混合结构体系【2012-3】指楼盖和屋盖采用钢筋混凝土或钢木结构,而墙和柱采用砌体结构建造的房屋,大多用在住宅、办公楼、教学楼建筑中。优点:抗压强度高,造价...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)