老物
新的公司让我去熟悉下Shiro框架,公司的项目的权限管理都是基于Shiro写的,照着前辈们的blog学习了一番,这里做点个人学习记录。*
Shiro 的整体架构图
首先是 Shiro 的几个组件
- SecurityManager
即所有 Subject 的管理者,这是 Shiro 框架的核心组件,可以把他看做是一个 Shiro 框架的全局管理组件,用于调度各种 Shiro 框架的服务。 - Authenticator
认证器,登入登出,对“Who are you?”进行核实。通常涉及用户名和密码。 - Authorizer
授权器,赋予主体有哪些权限,身份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、用户组、角色和 permission 的聚合体。 - Session Manager
这个组件保证了异构客户端的访问,配置简单。它是基于 POJO/J2SE 的,不跟任何的客户端或者协议绑定。 - Subject
即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro 中则需要通过 Subject 来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。 - Realms
Realms 也就是域,是用户的信息认证器和用户的权限人证器,我们需要自己来实现 Realms 来自定义的管理我们自己系统内部的权限规则。
通过 ini 文件来自定义 Realm
Maven 依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency>
shiro.ini
# ----------------------------------------------------------------------------- # Users and their (optional) assigned roles # username = password, role1, role2, ..., roleN # ----------------------------------------------------------------------------- [users] #用户名(登陆账号)是root,密码是123,角色是admin管理员 root = 123,admin user001 = 123,productManager user002 = 123,orderManager # ----------------------------------------------------------------------------- # Roles with assigned permissions # roleName = perm1, perm2, ..., permN # ----------------------------------------------------------------------------- [roles] #admin管理员权限拉满,什么都能做 admin = * #产品经理只能做产品的管理 productManager = addProduct,deleteProduct,editProduct,listProduct #订单管理员只能做订单的管理 orderManager = addOrder,deleteOrder,editOrder,listOrder
这里分配了三种角色各自拥有不同的权限
-
admin
- 拥有所有权限
-
productManager
- addProduct
- deleteProduct
- editProduct
- listProduct
-
orderManager
- addOrder
- deleteOrder
- editOrder
- listOrder
Tutorial .java
package shiro; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by MatthewHan on 2018. */ public class Tutorial { private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class); public static void main(String[] args) { //step1.使用了IniSecurityManagerFactory类读取ini文件 Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); //step2.解析ini文件,返回一个Securitymanager对象,对象含有配置信息 SecurityManager securityManager = factory.getInstance(); //step3. SecurityUtils.setSecurityManager(securityManager); //获取当前使用的用户 Subject currentUser = SecurityUtils.getSubject(); //获取Session信息 Session session = currentUser.getSession(); session.setAttribute("oneKey","aValue"); String value = (String)session.getAttribute("oneKey"); if(value.equals("trueValue")) { log.info("值正确!["+ value +"]"); } else { log.info("value有错误哦!您的value:["+ value+"]"); } log.info("\n**********************是否登陆成功*********************\n"); //登陆后的当前用户,这样我们就可以检查角色和权限: if(!currentUser.isAuthenticated()) { String username = "user001", password = "1123"; UsernamePasswordToken token = new UsernamePasswordToken(username, password); token.setRememberMe(true); try { currentUser.login(token);//登陆 log.info("你居然登陆上了,牛逼"); log.info("\n**********************打印这些登陆用户的信息*********************\n"); //打印这些登陆用户的信息 log.info("用户[" + currentUser.getPrincipal() + "] 登陆成功!"); //测试一个role String roleName = "productManager"; if (currentUser.hasRole(roleName)) { log.info("这个角色:[" + roleName + "]"); } else { log.info("emmmm,mere mortal!"); } log.info("\n**********************测试不同类型的权限*********************\n"); //测试不同类型的权限 if (currentUser.isPermitted("addProduct")) { log.info("您可以对产品进行管理"); } else { log.info("你不配使用"); } //part2 if (currentUser.isPermitted("addOrder")) { log.info("您可以对订单系统进行管理"); } else{ log.info("抱歉,你不配管理订单系统"); } } catch (UnknownAccountException uae) { log.info("没有这个用户名:" + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { log.info("这个账号" + token.getPrincipal() + "的密码是错的啦,try again?"); } catch (LockedAccountException lae) { log.info("这个用户" + token.getPrincipal() + "已被封锁" + "请联系管理员解锁"); } catch (AuthenticationException ae) { log.info("发生了一些未知的情况,请联系管理员!"); } } //用户登出 currentUser.logout(); System.exit(0); } }
测试类 Tutorial,通过 UsernamePasswordToken
创建的 token
对象来让 Subject
(当前对象)进行登陆验证,认证通过后,可以用 getPrincipal()
这个方法来获取当前对象的用户名。
角色相关验证方法
Subject 方法 | 描述 |
---|---|
hasRole(String roleName) | 当用户拥有指定角色时,返回 true |
hasRoles(List roleNames) | 按照列表顺序返回相应的一个 boolean 值数组 |
hasAllRoles(Collection roleNames) | 如果用户拥有所有指定角色时,返回 true |
Subject 方法 | 描述 |
---|---|
checkRole(String roleName) | 断言用户是否拥有指定角色 |
checkRoles(Collection roleNames) | 断言用户是否拥有所有指定角色 |
checkRoles(String... roleNames) | 对上一方法的方法重载 |
权限相关验证方法
Subject 方法 | 说明 |
---|---|
checkPermission(Permission p) | 断言用户是否拥有制定权限 |
checkPermission(String perm) | 断言用户是否拥有制定权限 |
checkPermissions(Collection perms) | 断言用户是否拥有所有指定权限 |
checkPermissions(String... perms) | 断言用户是否拥有所有指定权限 |
Subject 方法 | 描述 |
---|---|
isPermitted(Permission p) | Subject 拥有制定权限时,返回 true |
isPermitted(List perms) | 返回对应权限的 boolean 数组 |
isPermittedAll(Collection perms) | Subject 拥有所有制定权限时,返回 true |
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于