1.Shiro概念
在使用Shiro之前,大家写登陆都是五花八门的,
使用了Shiro这个安全框架之后,大家做权限的方式都统一了,这样的好处是:你的代码我看起来容易,我的代码你也好理解,Shiro比较成熟,基本上能满足大部分的权限需求。
2.RBAC概念
RBAC是当下权限系统的设计基础,有两种解释:
一:Role-Based Access Control,基于角色的访问控制
即:你要能够删除,那边当前用户就必须拥有这个角色。
二:Resource-Based Access Control,基于资源的访问控制
即:你要能够删除,那么当前用户就必须拥有这样的权限。
3.表结构
基于RBAC这个概念,就会存在3张基础表:用户、角色、权限,以及2张中间表来建立
用户与角色的多对多关系,
角色与权限的多对多关系,
用户与权限的多对多关系,他们是通过角色间接建立的。
4.Realm概念
Realm这个单词翻译为:域(很难理解为什么叫域)
Realm在Shiro扮演什么角色呢?
当应用程序向Shiro提供了账号和密码之后,Shiro会文Realm这个账号和密码是否正确,如果正确,其对应的用户就拥有哪些角色,哪些权限。
所以Realm其实就是个中介,他才是真正进行用户认证和授权的关键地方。
5.DatabaseRealm
DatabaseRealm就是通过数据库来验证用户和相关授权的类。
doGetAuthenticationInfo(),doGetAuthorizationInfo(),分别表示验证和授权。
DatabaseRealm这个类,用户提供,到那时不由用户自己调用,而是由Shiro去调用。
------------------------------2019.1.25完善------------------------------
介绍:
Apache Shiro处理身份认证,授权,企业会话管理和加密。
Apache Shiro的首要目标是易于使用和理解。从而简化开发人员的工作。
一、我们可以用shiro来做什么?
验证用户来核实他们的身份。
对用户执行访问控制。
判断用户是否被分配一个确定安全的角色。
判断用户是否允许做某些事情。
启用单点登陆(SSO)功能。
Subject:翻译为主角,当前参与应用安全部分的主角。可以是用户,可以试第三方服务,可以是cron 任务,或者任何东西。主要指一个正在与当前软件交互的东西。所有Subject都需要SecurityManager,当你与Subject进行交互,这些交互行为实际上被转换为与SecurityManager的交互。
SecurityManager:安全管理员,Shiro架构的核心,它就像Shiro内部所有原件的保护伞。然而一旦配置了SecurityManager,SecurityManager就用到的比较少,开发者大部分时间都花在Subject上面。请记得,当你与Subject进行交互的时候,实际上是SecurityManager在背后帮你举起Subject来做一些安全操作。
Realms:Realms作为Shiro和你的应用的连接桥,当需要与安全数据交互的时候,像用户账户,或者访问控制,Shiro就从一个或多个Realms中查找。Shiro提供了一些可以直接使用的Realms,如果默认的Realms不能满足你的需求,你也可以定制自己的Realms。
1.24-sihro权限管理,
用户身份认证和授权,简称认证授权
是否匿名
认证是否通过
用户名和密码身份验证
验证通过
身份认证:
授权:
必须进行身份认证,其次才能进行授权
1.身份验证
2.是否认证通过
3.权限控制
4.是否有访问权限
5.继续访问
三个主要概念:
Subject主体:当前操作用户(登陆、登出、访问会话、执行授权检查)
Principal:身份信息:标识符(用户名、手机号)唯一
credential:凭证信息(password)
SecurityManager:后台其他组件进行交互
Realms:应用安全管理器,数据库
Authenticator:认证器
Shiro-认证
二、自定义Realm登陆登出
整体架构
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion><groupId>cn.shiro.entry</groupId>
<artifactId>shiro-entry-test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
1.继承AuthorizingRealm,实现里面的2个方法(认证和授权),重写getName
2.新建shiro-realm.ini
3.登陆和登出
1.继承AuthorizingRealm,实现里面的2个方法(认证和授权),重写getName
package cn.shiro;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 1.继承AuthorizingRealm,实现里面的2个方法(认证和授权),重写getName
* 2.新建shiro-realm.ini
* 3.登陆和登出
*/
public class MyRealm extends AuthorizingRealm {
public String getName(){
return "MyRealm";
}
//授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println(token);
//获取到token中的用户名
String username = (String) token.getPrincipal();
//通过用户名查询数据库,将该用户对应的数据查询返回:账号和密码
if(!"admin".equals(username)){
return null;
}
String password = "12345";
//info对象表示realm登陆对比信息,参数1:用户信息,参数2:密码,参数3:当前realm名字
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,getName());
return info;
}
}
********2.新建shiro-realm.ini
#自定义realm
myRealm=cn.shiro.MyRealm
#指定securityManager的realms实现
securityManager.realms=$myRealm
********3.登陆和登出
package cn.shiro;
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;
import org.junit.Test;
public class ShiroTest {
@Test
public void testLoginByRealm() throws Exception {
//1.加载配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory
("classpath:shiro-realm.ini");
//2.通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = factory.getInstance();
//3.SecurityManager绑定到当前运行环境中,让系统随时都可以访问到SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4.创建当前登陆对象的主体,当前没有经过验证
Subject subject = SecurityUtils.getSubject();
//5.收集主体登陆的账号密码
UsernamePasswordToken token = new UsernamePasswordToken("admin","12345");
//6.主体登陆
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
//7.判断是否成功
System.out.println("登陆情况:"+subject.isAuthenticated());
//8.登出(注销)
System.out.println("登陆情况:"+subject.isAuthenticated());
subject.logout();
}
@Test
public void testShiro() throws Exception {
//1.加载配置文件
Factory<SecurityManager> factory = new IniSecurityManagerFactory
("classpath:shiro.ini");
//2.通过工厂对象,创建SecurityManager对象
SecurityManager securityManager = factory.getInstance();
//3.SecurityManager绑定到当前运行环境中,让系统随时都可以访问到SecurityManager对象
SecurityUtils.setSecurityManager(securityManager);
//4.创建当前登陆对象的主体,当前没有经过验证
Subject subject = SecurityUtils.getSubject();
//5.收集主体登陆的账号密码
UsernamePasswordToken token = new UsernamePasswordToken("admin","12345");
//6.主体登陆
try {
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
}
//7.判断是否成功
System.out.println("登陆情况:"+subject.isAuthenticated());
//8.登出(注销)
System.out.println("登陆情况:"+subject.isAuthenticated());
subject.logout();
}
}