老物
新的公司让我去熟悉下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 |
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于