Shiro-Realm

2024-08-21 00:32
文章标签 shiro realm

本文主要是介绍Shiro-Realm,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Realm:域,Shiro 从从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看
成DataSource , 即安全数据源。如我们之前的ini 配置方式将使用
org.apache.shiro.realm.text.IniRealm

public interface Realm {/***返回一个唯一的Realm名字,这个用来标识* @return the (application-unique) name assigned to this <code>Realm</code>.*/String getName();//判断此Realm是否支持此Token.不支持将不进行校验boolean supports(AuthenticationToken token);//根据Token获取认证信息AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;}
[main]
#声明一个realm
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
#指定securityManager的realms实现
securityManager.realms=$myRealm1

这里,我们来看一下,怎么把配置文件的信息初始化在securityManager中的realms中的,之前我们知道,初始化的时候,会把信息加载在Ini类中去,看看怎么初始化信息。之前我还没有看懂,断点跟着看懂了。
这里写图片描述
SecurityManager securityManager = factory.getInstance();从这句话跟着进入
AbstractFactory 工厂方法的模板创建的方式,留给子类去处理信息。
这里写图片描述

IniFactorySupport
这里写图片描述
之前这里说过,如果有配置文件和没有配置文件的两种处理方式
这里写图片描述
IniSecurityManagerFactory这里再次使用父类的模板方法
这里写图片描述

这里写图片描述

IniSecurityManagerFactory->createSecurityManager
从配置文件中的信息,main这个配置拿出来啦
这里写图片描述
之后创建默认的SecurityManager…
ReflectionBuilder 通过反射创建配置的信息的对象哦~~

private Map<String, ?> buildInstances(Ini.Section section, Map<String, ?> defaults) {this.builder = new ReflectionBuilder(defaults);return this.builder.buildObjects(section);}//ReflectionBuilder 里面就是一个HashMap就是操作,把SecurityManager创建好的也放置在里面,创建的Realm也是放置在里面最后的时候在处理SecurityManager里面的Realms。。。
public ReflectionBuilder(Map<String, ?> defaults) {this.objects = CollectionUtils.isEmpty(defaults) ? new LinkedHashMap<String, Object>() : defaults;}

这里写图片描述

然后将创建实例reaml 和设置属性的值
实例:myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
属性:securityManager.realms= myRealm1objectHashMap myRealm1,去HashMap找到实例了,哈哈。

Map<String, String> instanceMap = new LinkedHashMap<String, String>();Map<String, String> propertyMap = new LinkedHashMap<String, String>();for (Map.Entry<String, String> entry : kvPairs.entrySet()) {if (entry.getKey().indexOf('.') < 0 || entry.getKey().endsWith(".class")) {instanceMap.put(entry.getKey(), entry.getValue());} else {propertyMap.put(entry.getKey(), entry.getValue());}}

创建realm实例..通过反射,放置在HashMap中,之后我们就清楚了啊!创建成果啦按哈哈

 // Create all instancesfor (Map.Entry<String, String> entry : instanceMap.entrySet()) {createNewInstance((Map<String, Object>) objects, entry.getKey(), entry.getValue());}// Set all propertiesfor (Map.Entry<String, String> entry : propertyMap.entrySet()) {applyProperty(entry.getKey(), entry.getValue(), objects);}
   protected void createNewInstance(Map<String, Object> objects, String name, String value) {Object currentInstance = objects.get(name);if (currentInstance != null) {log.info("An instance with name '{}' already exists.  " +"Redefining this object as a new instance of type {}", name, value);}Object instance;//name with no property, assume right hand side of equals sign is the class name:try {//根据全限定名哦~~反射创建instance = ClassUtils.newInstance(value);if (instance instanceof Nameable) {((Nameable) instance).setName(name);}} catch (Exception e) {String msg = "Unable to instantiate class [" + value + "] for object named '" + name + "'.  " +"Please ensure you've specified the fully qualified class name correctly.";throw new ConfigurationException(msg, e);}objects.put(name, instance);}

之前我们看到过验证的流程,主要是我们没有涉及到Realm
1、首先调用Subject.login(token)进行登录,其会自动委托给Security Manager,调用之前必须通过SecurityUtils. setSecurityManager()设置;
2、SecurityManager负责真正的身份验证逻辑;它会委托给Authenticator进行身份验证;
3、Authenticator才是真正的身份验证者,Shiro API中核心的身份认证入口点,此处可以自定义插入自己的实现;
4、Authenticator可能会委托给相应的AuthenticationStrategy进行多Realm身份验证,默认ModularRealmAuthenticator会调用AuthenticationStrategy进行多Realm身份验证;
5、Authenticator 会把相应的token 传入Realm,从Realm 获取身份验证信息,如果没有返回/抛出异常表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。

下面也是一样的跟着进入看看设计
subject.login–>DelegatingSubject.login–>securityManager.login(this, token);一步步的代理进入,主要管理主要的业务逻辑,这样进入到了管家的login
这里写图片描述
这里我们可以看到管家的结构形式,慢慢的验证逻辑就会进入到具体的验证的函数中去
这里写图片描述

AuthenticatingSecurityManager

private Authenticator authenticator;public AuthenticatingSecurityManager() {super();this.authenticator = new ModularRealmAuthenticator();}/*** Delegates to the wrapped {@link org.apache.shiro.authc.Authenticator Authenticator} for authentication.*///通过代理进入到具体的实现处理逻辑的类中去public AuthenticationInfo authenticate(AuthenticationToken token) throws AuthenticationException {return this.authenticator.authenticate(token);}

这里依然运用了模板方法哦!
这里写图片描述

AbstractAuthenticator->authenticate(AuthenticationToken token)中调用了子类的信息ModularRealmAuthenticator->doAuthenticate(AuthenticationToken authenticationToken)

 protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {assertRealmsConfigured();Collection<Realm> realms = getRealms();if (realms.size() == 1) {return doSingleRealmAuthentication(realms.iterator().next(), authenticationToken);} else {return doMultiRealmAuthentication(realms, authenticationToken);}}

然后调用相应的realm进行处理哦,这里是单个的情况!

protected AuthenticationInfo doSingleRealmAuthentication(Realm realm, AuthenticationToken token) {if (!realm.supports(token)) {String msg = "Realm [" + realm + "] does not support authentication token [" +token + "].  Please ensure that the appropriate Realm implementation is " +"configured correctly or that the realm accepts AuthenticationTokens of this type.";throw new UnsupportedTokenException(msg);}AuthenticationInfo info = realm.getAuthenticationInfo(token);if (info == null) {String msg = "Realm [" + realm + "] was unable to find account data for the " +"submitted AuthenticationToken [" + token + "].";throw new UnknownAccountException(msg);}return info;}

我们自定义中必须实现的函数就好了realm.getAuthenticationInfo(token);

public class MyRealm1 implements Realm {@Overridepublic String getName() {return "myrealm1";}@Overridepublic boolean supports(AuthenticationToken token) {return token instanceof UsernamePasswordToken; //仅支持UsernamePasswordToken类型的Token}@Overridepublic AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String username = (String)token.getPrincipal();  //得到用户名String password = new String((char[])token.getCredentials()); //得到密码if(!"zhang".equals(username)) {throw new UnknownAccountException(); //如果用户名错误}if(!"123".equals(password)) {throw new IncorrectCredentialsException(); //如果密码错误}//如果身份认证验证成功,返回一个AuthenticationInfo实现;return new SimpleAuthenticationInfo(username, password, getName());}
}

AbstractAuthenticator这里还有经典的设计模式监听,然后进行通知,名字忘了哈哈设计的非常的用心哦

public abstract class AbstractAuthenticator implements Authenticator, LogoutAware {/*** Any registered listeners that wish to know about things during the authentication process.*/private Collection<AuthenticationListener> listeners;public AbstractAuthenticator() {listeners = new ArrayList<AuthenticationListener>();}public void setAuthenticationListeners(Collection<AuthenticationListener> listeners) {if (listeners == null) {this.listeners = new ArrayList<AuthenticationListener>();} else {this.listeners = listeners;}}public Collection<AuthenticationListener> getAuthenticationListeners() {return this.listeners;}protected void notifySuccess(AuthenticationToken token, AuthenticationInfo info) {for (AuthenticationListener listener : this.listeners) {listener.onSuccess(token, info);}}//消息还传送哦~~订阅模式protected void notifyFailure(AuthenticationToken token, AuthenticationException ae) {for (AuthenticationListener listener : this.listeners) {listener.onFailure(token, ae);}}protected void notifyLogout(PrincipalCollection principals) {for (AuthenticationListener listener : this.listeners) {listener.onLogout(principals);}}public void onLogout(PrincipalCollection principals) {notifyLogout(principals);}public final AuthenticationInfo authenticate(AuthenticationToken token)throws AuthenticationException {if (token == null) {throw new IllegalArgumentException("Method  null.");}log.trace("Authentication attempt received for token [{}]", token);AuthenticationInfo info;try {info = doAuthenticate(token);if (info == null) {throw new AuthenticationException(msg);}} catch (Throwable t) {AuthenticationException ae = null;if (t instanceof AuthenticationException) {ae = (AuthenticationException) t;}if (ae == null) {ae = new AuthenticationException(msg, t);}try {notifyFailure(token, ae);} catch (Throwable t2) {if (log.isWarnEnabled()) {log.warn(msg, t2);}}throw ae;}log.debug("Authentication successful for token [{}].  Returned account [{}]", token, info);notifySuccess(token, info);return info;}//模板方法protected abstract AuthenticationInfo doAuthenticate(AuthenticationToken token)throws AuthenticationException;}

public interface AuthenticationListener {void onSuccess(AuthenticationToken token, AuthenticationInfo info);void onFailure(AuthenticationToken token, AuthenticationException ae);void onLogout(PrincipalCollection principals);
}

多种模式选择策越进行处理。具体的策越模式还没有进行了解~~

这篇关于Shiro-Realm的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1091609

相关文章

【Shiro】Shiro 的学习教程(三)之 SpringBoot 集成 Shiro

目录 1、环境准备2、引入 Shiro3、实现认证、退出3.1、使用死数据实现3.2、引入数据库,添加注册功能后端代码前端代码 3.3、MD5、Salt 的认证流程 4.、实现授权4.1、基于角色授权4.2、基于资源授权 5、引入缓存5.1、EhCache 实现缓存5.2、集成 Redis 实现 Shiro 缓存 1、环境准备 新建一个 SpringBoot 工程,引入依赖:

【Shiro】Shiro 的学习教程(二)之认证、授权源码分析

目录 1、背景2、相关类图3、解析3.1、加载、解析阶段3.2、认证阶段3.3、授权阶段 1、背景 继上节代码,通过 debug 进行 shiro 源码分析。 2、相关类图 debug 之前,先了解下一些类的结构图: ①:SecurityManager:安全管理器 DefaultSecurityManager: RememberMeManager:实现【记住我】功能

【Shiro】Shiro 的学习教程(一)之快速入门

目录 1、Shiro 简介2、Shiro 认证、授权2.1、认证2.2、授权 3、快速入门4、自定义 Realm5、加密6、实现授权 1、Shiro 简介 Shiro 官网:https://shiro.apache.org/ Shiro 是一个功能强大且易于使用的 Java 安全框架,它执行身份验证、授权、加密和会话管理。使用 Shiro 易于理解的 API,您可以快速轻松地保

shiro session 监听

spring 使用 shiro 后,由于shiro重新封装了原有的session,所以不能再使用原来的session监听方法了 (1)在shiro配额只文件中设置监听类   <!-- shiroSessionListener  监听类--><bean id="shiroSessionListener" class="com.listener.ShiroSessionListener"></

Shiro身份认证流程

http://www.toutiao.com/a6353832181929279746/?tt_from=mobile_qq&utm_campaign=client_share&app=explore_article&utm_source=mobile_qq&iid=5840657922&utm_medium=toutiao_ios

Shiro-721漏洞详解及复现

之前有些Shiro-550反序列化漏洞的文章Shiro-550漏洞详解及复现_shiro框架漏洞-CSDN博客 这里简单补充一下关于Shiro-721漏洞的内容。 目录 Shiro-721漏洞原理 Padding Oracle攻击 利用条件 影响版本 漏洞复现 Shiro-721漏洞原理 Shiro-721用到的加密方式是AES-128-CBC,跟Shiro-550最大的

进阶SpringBoot之 Shiro(6)整合 Thymeleaf

Subject:用户 SecurityManager:管理所有用户 Realm:连接数据 pom.xml 导入 thymeleaf-extras-shiro 的 jar 包,整合 shiro-thymeleaf <!-- shiro-thymeleaf 整合 --><dependency><groupId>com.github.theborakompanioni</grou

Shiro的认证原理(Subject#login的背后故事)

登录操作一般都是我们触发的: Subject subject = SecurityUtils.getSubject();AuthenticationToken authenticationToken = new ...subject.login(authenticationToken); Subject的登录将委托给SecurityManager,SecurityManager的logi

Shiro过滤器的维护与匹配执行

servlet的初始化会触发核心过滤器的创建: public Object getObject() throws Exception {if (instance == null) {instance = createInstance();}return instance;} 在createInstance方法中会调用 FilterChainManager manager = create

shiro的使用入门

shiro是一个权限控制框架,因为项目需要自己看了看,在这里把所有学到的分享一下。shiro主要由AuthorizationInfo、AuthenticationInfo、Subject构成一个权限环境,doGetAuthenticationInfo方法是用户登录的使用调用的( subject.login(token);),doGetAuthorizationInfo方法是在用户进行权限验