简介
Shiro 是当下常见的安全框架,主要用于用户验证和授权操作。
如同 spring security 一样都是是一个权限安全框架,但是与Spring Security相比,在于他使用了和比较简洁易懂的认证和授权方式。
Shiro的核心组件:
- Subject :当前用户的操作
- SecurityManager:用于管理所有的Subject
- Realms:用于进行权限信息的验证
Subject:即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。
SecurityManager:即所有Subject的管理者,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。
Realms:Realms则是用户的信息认证器和用户的权限人证器,我们需要自己来实现Realms来自定义的管理我们自己系统内部的权限规则。
实现方式
在shiro的用户权限认证过程中其通过两个方法来实现:
1、Authentication:是验证用户身份的过程。
2、Authorization:是授权访问控制,用于对用户进行的操作进行人证授权,证明该用户是否允许进行当前操作,如访问某个链接,某个资源文件等。
创建Shiro项目
使用IDEA创建maven项目,在pom.xml中添加依赖:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
</dependency>
使用shiro
Shiro提供了一个通用的方案通过 INI 进行配置 ,当然也可以通过XML,YMAL,JSON等进行配置。
在resource目录下面,创建一个shiro.ini的文件。内容如下:
#定义用户
[users]
#用户名 zhang3 密码是 12345, 角色是 admin
zhang3 = 12345,admin
#用户名 li4 密码是 abcde, 角色是 产品经理
li4 = abcde,productManager
#定义角色
[roles]
#管理员什么都能做
admin = *
#产品经理只能做产品管理
productManager = addProduct,deleteProduct,editProduct,updateProduct,listProduct
#订单经理只能做产品管理
orderManager = addOrder,deleteOrder,editOrder,updateOrder,listOrder
- 创建User对象
package cn.jp.shiro.pojo;
/**
* @author JP
* @title: User
* @projectName studyShiro
* @description:准备用户类,存储账户和密码
*
* @date 2019/2/22 00229:18
*/
public class User {
private String name;
private String password;
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- 创建一个TestShiro测试类
package cn.jp.shiro.test;
import java.util.ArrayList;
import java.util.List;
import cn.jp.shiro.pojo.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
/**
* @author JP
* @title: TestShiro
* @projectName studyShiro
* @description:测试shiro安全框架
* @date 2019/2/22 00229:22
*/
public class TestShiro {
public static void main(String[] args) {
User zhang3 = new User();
zhang3.setName("zhang3");
zhang3.setPassword("12345");
User li4 = new User();
li4.setName("li4");
li4.setPassword("abcde");
User wang5 = new User();
wang5.setName("wang5");
wang5.setPassword("wrongpassword");
List<User> users = new ArrayList<>();
users.add(zhang3);
users.add(li4);
users.add(wang5);
//角色们
String roleAdmin = "admin";
String roleProductManager = "productManager";
String orderManager = "orderManager";
List<String> roles = new ArrayList<>();
roles.add(roleAdmin);
roles.add(roleProductManager);
roles.add(orderManager);
//权限们
String permitAddProduct = "addProduct";
String permitAddOrder = "addOrder";
String permitDeleteProduct = "deleteProduct";
List<String> permits = new ArrayList<>();
permits.add(permitAddProduct);
permits.add(permitAddOrder);
permits.add(permitDeleteProduct);
//登录每个用户
for (User user : users) {
if (login(user)) {
System.out.printf("%s \t成功登陆,用的密码是 %s\t %n", user.getName(), user.getPassword());
} else {
System.out.printf("%s \t成功失败,用的密码是 %s\t %n", user.getName(), user.getPassword());
}
}
System.out.println("------- 分割线------");
//判断能够登录的用户是否拥有某个角色
for (User user : users) {
for (String role : roles) {
if (login(user)) {
if (TestShiro.hasRole(user, role)) {
System.out.printf("%s\t 拥有角色: %s\t%n", user.getName(), role);
} else {
System.out.printf("%s\t 不拥有角色: %s\t%n", user.getName(), role);
}
}
}
}
System.out.println("------- 分割线------");
for(User user:users){
for(String permit:permits){
if(login(user)){
if(isPermitted(user,permit)){
System.out.printf("%s\t 拥有权限: %s\t%n",user.getName(),permit);
}else{
System.out.printf("%s\t 不拥有权限: %s\t%n",user.getName(),permit);
}
}
}
}
}
/**
* @return
* @Author jp
* @Description //TODO 用户拥有角色
* @Date 9:37 2019/2/22 0022
* @Param
**/
public static boolean hasRole(User user, String role) {
Subject subject = getSubject(user);
return subject.hasRole(role);
}
/**
* @return
* @Author jp
* @Description //TODO 判断是否拥有权限
* @Date 9:39 2019/2/22 0022
* @Param
**/
public static boolean isPermitted(User user, String permit) {
Subject subject = getSubject(user);
return subject.isPermitted(permit);
}
/**
* @Author jp
* @Description //TODO
* @Date 10:21 2019/2/22 0022
* @Param
* @return
**/
private static Subject getSubject(User user) {
//加载配置文件,获取工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//获取安全管理实例
SecurityManager sm = factory.getInstance();
//将安全管理sui者放入全局对象
SecurityUtils.setSecurityManager(sm);
//全局对象通过安全管理者生成Subject对象
Subject subject = SecurityUtils.getSubject();
return subject;
}
/**
* @return
* @Author jp
* @Description //TODO 判断用户是否登录
* @Date 9:35 2019/2/22 0022
* @Param
**/
private static boolean login(User user) {
Subject subject = getSubject(user);
//如果已经登录,退出
if (subject.isAuthenticated())
subject.logout();
//封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
try {
//将用户数据token,最终传递到Realm中进行对比
subject.login(token);
} catch (AuthenticationException e) {
//验证错误
return false;
}
return subject.isAuthenticated();
}
}
- 实现效果
当输入的账户与shiro.ini配置文件里账户匹配时,登录成功,然后验证角色所拥有的权限~