在单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验证的更多相关文章

  1. shiro双realm验证

    假设现在有这样一种需求:存在两张表user和admin,分别记录普通用户和管理员的信息.并且现在要实现普通用户和管理员的分开登录,即需要两个Realm——UserRealm和AdminRealm,分别 ...

  2. shiro多realm验证之——shiro实现不同身份使用不同Realm进行验证(转)

    转自: http://blog.csdn.net/xiangwanpeng/article/details/54802509 (使用特定的realm实现特定的验证) 假设现在有这样一种需求:存在两张表 ...

  3. Shiro自定义realm实现密码验证及登录、密码加密注册、修改密码的验证

    一:先从登录开始,直接看代码 @RequestMapping(value="dologin",method = {RequestMethod.GET, RequestMethod. ...

  4. Shiro固定身份验证

    Shiro基础身份验证 如果要进行shiro的日志信息读取,那么需要使用一个org.apache.shiro.util.Factory接口,在这个接口里面定义有一 取得SecuruityManager ...

  5. 基于权限安全框架Shiro的登录验证功能实现

    目前在企业级项目里做权限安全方面喜欢使用Apache开源的Shiro框架或者Spring框架的子框架Spring Security. Apache Shiro是一个强大且易用的Java安全框架,执行身 ...

  6. Shiro笔记(四)Shiro的realm认证

    认证流程: 1.获取当前Subject.调用SecurityUtils.getSubject(); 2.测试当前用户是否已经被认证,即是否已经登录,调用Subject的isAurhenticated( ...

  7. Shiro中Realm

    6.1 Realm [2.5 Realm]及[3.5 Authorizer]部分都已经详细介绍过Realm了,接下来再来看一下一般真实环境下的Realm如何实现. 1.定义实体及关系   即用户-角色 ...

  8. shiro登陆权限验证

    一>引入shirojar包 <!-- shiro登陆权限控制 -->        <dependency>            <groupId>org. ...

  9. shiro自定义Realm

    1.1 自定义Realm 上边的程序使用的是shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm. ...

随机推荐

  1. 第八周学习总结&实验报告六

    实验总结 :类的继承 实验目的 理解异常的基本概念: 掌握异常处理方法及熟悉常见异常的捕获方法. 实验要求 : 练习捕获异常.声明异常.抛出异常的方法.熟悉try和catch子句的使用. 掌握自定义异 ...

  2. Shell执行脚本

    Shell作用是解释执行用户的命令,用户输入一条命令,Shell就解释执行这一条,这种方式称为交互式,但还有另一种执行命令的方式称为批处理方式,用户事先写一个Shell脚本,Shell可以一次把这些命 ...

  3. CRC32算法C#中的实现

    代码如下: using System; using System.Collections.Generic; using System.Text; using System.IO; namespace ...

  4. leetcode-easy-dynamic-70 Climbing Stairs

    mycode  65% class Solution(object): def climbStairs(self, n): """ :type n: int :rtype ...

  5. python - jpype模块,python调用java的接口

    转载自: http://www.cnblogs.com/junrong624/p/5278457.html https://www.cnblogs.com/fanghao/p/7745356.html ...

  6. flutter button

    flutter button button类型: RaisedButton : 凸起的按钮,其实就是Android中的Material Design风格的Button ,继承自MaterialButt ...

  7. nmon报告指标含义

    nmon分析文件详细指标详解指标类型指标名称指标含义SYS_SUMMCPU%cpu占有率变化情况:IO/secIO的变化情况:AAAAIXAIX版本号:buildbuild版本号:command执行命 ...

  8. 什么是lambda?有什么好处

    lambda 函数是一个可以接收任意多个参数(包括可选参数)并且返回单个表达式值的函数 1.lambda 函数比较轻便,即用即仍,很适合需要完成一项功能,但是此功能只在此一处使用,连名字都很随意的情况 ...

  9. nginx启动用户和nginx工作用户要一致

    [root@bogon default]# ps aux | grep "nginx: worker process" | awk '{print $1}'rootrootroot ...

  10. CSS3 —— 盒子模型

    盒子模型 主要的属性就5个:width.height.padding.border.margin.如下:  width和height:内容的宽度.高度(不是盒子的宽度.高度). padding:内边距 ...