Shiro多Realm验证
在单Realm的基础上,进行如下内容的修改
原有的ShiroRealm.java:
package com.atguigu.shiro.realms; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource; public class ShiroRealm extends AuthenticatingRealm { @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("[ShiroRealm] doGetAuthenticationInfo"); //1. 把AuthenticationToken 转换为 UsernamePasswordToken
UsernamePasswordToken upToken = (UsernamePasswordToken)token; //2. 从UsernamePasswordToken 中来获取username
String username = upToken.getUsername(); //3.调用数据库的方法,从数据库查询username 对应的用户记录
System.out.println("从数据库中获取username:" + username +" 所对应的用户信息"); //4.若用户不存在可以抛出 UnknownAccountException 异常
if ("unknown".equals(username)) {
throw new UnknownAccountException("用户不存在");
} //5.根据用户信息的情况,决定是否抛出其它的 AuthenticationException 异常
if ("monster".equals(username)) {
throw new LockedAccountException("用户被锁定");
} //6.根据用户的情况,来构建 AuthenticationToken 对象并返回,通常使用的实现类为:SimpleAuthenticationInfo
//一下信息是从数据库中获取的
//1).principals:认证的实体信息,可以是username,也可以是数据表对应的实体类对象
Object principal = username;
//2).credentials:密码
Object hashedCredentials = null; //"fc1709d0a95a6be30bc5926fdb7f22f4";
if ("admin".equals(username)) {
hashedCredentials = "038bdaf98f2037b31f1e75b5b4c9b26e";
}else if("user".equals(username)) {
hashedCredentials = "098d2c478e9c11555ce2823231e02ec1";
} //3).realmName:当前realm 对象的name,调用父类的getName()方法即可
String realmName = getName();
//4).盐值
//SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credential,realmName);
//因为用户名唯一,使用用户名作为盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, realmName);
return info;
} public static void main(String[] args) {
String algorithmName = "MD5";
Object password = "123456";
Object salt = ByteSource.Util.bytes("admin");
int hashIterations = 1024;
Object result = new SimpleHash(algorithmName, password, salt, hashIterations);
System.out.println(result);
} }
添加SecondRealm.java:
package com.atguigu.shiro.realms; import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource; public class SecondRealm extends AuthenticatingRealm { @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("[SecondRealm] doGetAuthenticationInfo"); //1. 把AuthenticationToken 转换为 UsernamePasswordToken
UsernamePasswordToken upToken = (UsernamePasswordToken)token; //2. 从UsernamePasswordToken 中来获取username
String username = upToken.getUsername(); //3.调用数据库的方法,从数据库查询username 对应的用户记录
System.out.println("从数据库中获取username:" + username +" 所对应的用户信息"); //4.若用户不存在可以抛出 UnknownAccountException 异常
if ("unknown".equals(username)) {
throw new UnknownAccountException("用户不存在");
} //5.根据用户信息的情况,决定是否抛出其它的 AuthenticationException 异常
if ("monster".equals(username)) {
throw new LockedAccountException("用户被锁定");
} //6.根据用户的情况,来构建 AuthenticationToken 对象并返回,通常使用的实现类为:SimpleAuthenticationInfo
//一下信息是从数据库中获取的
//1).principals:认证的实体信息,可以是username,也可以是数据表对应的实体类对象
Object principal = username;
//2).credentials:密码
Object hashedCredentials = null; //"fc1709d0a95a6be30bc5926fdb7f22f4";
if ("admin".equals(username)) {
hashedCredentials = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";
}else if("user".equals(username)) {
hashedCredentials = "073d4c3ae812935f23cb3f2a71943f49e082a718";
} //3).realmName:当前realm 对象的name,调用父类的getName()方法即可
String realmName = getName();
//4).盐值
//SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credential,realmName);
//因为用户名唯一,使用用户名作为盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, hashedCredentials, credentialsSalt, realmName);
return info;
} public static void main(String[] args) {
String algorithmName = "SHA1";
Object password = "123456";
Object salt = ByteSource.Util.bytes("admin");
int hashIterations = 1024;
Object result = new SimpleHash(algorithmName, password, salt, hashIterations);
System.out.println(result);
} }
修改applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- =========================================================
Shiro Core Components - Not Spring Specific
========================================================= -->
<!-- Shiro's main business-tier object for web-enabled applications
(use DefaultSecurityManager instead when there is no web environment)-->
<!--
1.配置SecurityManager!
-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/>
<!-- 单个Realm -->
<!-- <property name="realm" ref="jdbcRealm"/> -->
<!-- 多Realm -->
<property name="authenticator" ref="authenticator"/>
</bean> <!-- Let's use some enterprise caching support for better performance. You can replace this with any enterprise
caching framework implementation that you like (Terracotta+Ehcache, Coherence, GigaSpaces, etc --> <!--
2.配置cacheManager
2.1 需要加入ehcache的jar包及配置文件
-->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- Set a net.sf.ehcache.CacheManager instance here if you already have one. If not, a new one
will be creaed with a default config:
<property name="cacheManager" ref="ehCacheManager"/> -->
<!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
a specific Ehcache configuration to be used, specify that here. If you don't, a default
will be used.: -->
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean> <!-- 将两个Realm配置到认证器中 -->
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="realms">
<list>
<ref bean="jdbcRealm"/>
<ref bean="secondRealm"/>
</list>
</property>
</bean>
<!-- Used by the SecurityManager to access security data (users, roles, etc).
Many other realm implementations can be used too (PropertiesRealm,
LdapRealm, etc. --> <!--
3.配置Realm
3.1直接配置实现了com.atguigu.shiro.realms.ShiroRealm接口的bean
-->
<bean id="jdbcRealm" class="com.atguigu.shiro.realms.ShiroRealm">
<!-- 配置MD5加密 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 指定加密方式为MD5 -->
<property name="hashAlgorithmName" value="MD5"></property>
<!-- 指定加密次数 -->
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean> <bean id="secondRealm" class="com.atguigu.shiro.realms.SecondRealm">
<!-- 配置MD5加密 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 指定加密方式为MD5 -->
<property name="hashAlgorithmName" value="SHA1"></property>
<!-- 指定加密次数 -->
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean> <!-- =========================================================
Shiro Spring-specific integration
========================================================= -->
<!-- Post processor that automatically invokes init() and destroy() methods
for Spring-configured Shiro objects so you don't have to
1) specify an init-method and destroy-method attributes for every bean
definition and
2) even know which Shiro objects require these methods to be
called. -->
<!--
4.配置LifecycleBeanPostProcessor,可以自动地来调用配置在Spring IOC容器中shiro bean的生命周期方法
-->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- Enable Shiro Annotations for Spring-configured beans. Only run after
the lifecycleBeanProcessor has run: --> <!--
5.启用IOC容器中使用shiro的注解,但必须在配置了LifecycleBeanPostProcessor之后才可以使用
-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor"/>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"/>
</bean> <!-- Define the Shiro Filter here (as a FactoryBean) instead of directly in web.xml -
web.xml uses the DelegatingFilterProxy to access this bean. This allows us
to wire things with more control as well utilize nice Spring things such as
PropertiesPlaceholderConfigurer and abstract beans or anything else we might need: --> <!--
6.配置ShiroFilter
6.1 id必须和web.xml文件中配置的DelegatingFilterProxy的 <filter-name> 一致
若不一致,则会抛出:NoSuchBeanDefinitionException. 因为 Shiro 会来 IOC 容器中查找和 <filter-name> 名字对应的 filter bean.
6.2
-->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/list.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/> <!--
配置哪些页面需要受保护
以及访问这些页面需要的权限
1). anon 可以被匿名访问
2). authc 必须认证(即登录)后才可以访问的页面
3). logout 登出
-->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/shiro/login = anon
/shiro/logout = logout
# everything else requires authentication:
/** = authc
</value>
</property>
</bean>
</beans>
Shiro多Realm验证的更多相关文章
- shiro双realm验证
假设现在有这样一种需求:存在两张表user和admin,分别记录普通用户和管理员的信息.并且现在要实现普通用户和管理员的分开登录,即需要两个Realm——UserRealm和AdminRealm,分别 ...
- shiro多realm验证之——shiro实现不同身份使用不同Realm进行验证(转)
转自: http://blog.csdn.net/xiangwanpeng/article/details/54802509 (使用特定的realm实现特定的验证) 假设现在有这样一种需求:存在两张表 ...
- Shiro自定义realm实现密码验证及登录、密码加密注册、修改密码的验证
一:先从登录开始,直接看代码 @RequestMapping(value="dologin",method = {RequestMethod.GET, RequestMethod. ...
- Shiro固定身份验证
Shiro基础身份验证 如果要进行shiro的日志信息读取,那么需要使用一个org.apache.shiro.util.Factory接口,在这个接口里面定义有一 取得SecuruityManager ...
- 基于权限安全框架Shiro的登录验证功能实现
目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security. Apache Shiro是一个强大且易用的Java安全框架,执行身 ...
- Shiro笔记(四)Shiro的realm认证
认证流程: 1.获取当前Subject.调用SecurityUtils.getSubject(); 2.测试当前用户是否已经被认证,即是否已经登录,调用Subject的isAurhenticated( ...
- Shiro中Realm
6.1 Realm [2.5 Realm]及[3.5 Authorizer]部分都已经详细介绍过Realm了,接下来再来看一下一般真实环境下的Realm如何实现. 1.定义实体及关系 即用户-角色 ...
- shiro登陆权限验证
一>引入shirojar包 <!-- shiro登陆权限控制 --> <dependency> <groupId>org. ...
- shiro自定义Realm
1.1 自定义Realm 上边的程序使用的是shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm. ...
随机推荐
- Java_IO流实验
实验题目链接:Java第09次实验(IO流) 0. 字节流与二进制文件 我的代码 package experiment.io; import java.io.DataInputStream; impo ...
- JavaScript 普通声明式函数
1.为什么需要函数 实现代码的复用.存在函数提升,且会在变量提升的上面; 2.函数的创建 js中函数语法: function 函数名(形参){ //函数体 } 调用时:函数名(形参) 注: (1) 形 ...
- 胜利点20191010-6 alpha week 1/2 Scrum立会报告+燃尽图 04
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8749 一.小组情况组长:贺敬文组员:彭思雨 王志文 位军营 杨萍队名:胜 ...
- golang tcp keepalive实践
前文中已经介绍了TCP keep alive的做了详尽说明,本文结合golang,介绍如何使用TCP keep alive. 目前golang net包不提供TCP keep alive 空闲多长时间 ...
- CountDownLatch用法实践
项目中写多线程时,需要判断所有线程是否执行完毕,所以想到了添加累加器来判断.这个累加器使用什么变量,找到了以下2种方式. 1. 类似AtomicInteger这种提供原子操作的类型AtomicInte ...
- 创建一个包含TC的Alpine镜像
镜像的创建 更换镜像至ustc(为了测试时的速度) 安装musl-dev make gcc linux-headers bison flex以使TC可以编译 拷贝进TC的源代码 进入源代码文件夹进行编 ...
- Python学习之==>面向对象编程(二)
一.类的特殊成员 我们在Python学习之==>面向对象编程(一)中已经介绍过了构造方法和析构方法,构造方法是在实例化时自动执行的方法,而析构方法是在实例被销毁的时候被执行,Python类成员中 ...
- playbook部署mangodb
playbook文件 [root@localhost ~]# cat deploy_mongo.yaml --- - hosts: webservers become: yes become_meth ...
- Django 中 ModelForm 的使用
定义 ModelForm 定制 ModelForm Meta 在 Form 中另外定义 Field 值得一提的一些 Field 转化 AutoField BooleanField ForeignKey ...
- python学习之数据类型(List)
3.5 列表 3.5.1 列表的介绍 列表是python的基础数据类型之⼀,其他编程语言也有类似的数据类型. 比如JS中的数组, java中的数组等等.它是以[ ]括起来, 每个元素⽤' , '隔 ...