shiro加密认证-多realm下

前面有说到一个realm下,如果有多realm下呢?

比如有两个数据库,一个MySQL使用MD5加密,而另一个oracle使用SHA1加密,那么该如何写呢?

这里先介绍一下认证策略。

我们在realms文件夹下新建立一个SecondRealm.java:

package com.atguigu.shiro.realms;

import org.apache.shiro.authc.*;
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.根据用户的情况,来构建AuthenticationInfo对象并且返回
        //通常使用的实现类是SimpleAuthenticationInfo
        //以下信息从数据库中获取
        //<1.principal:认证的实体信息,可以是username也可以是数据表对应的实体类对象
        Object principal=username;
        //<2.credentials:密码
        Object credentials=null;
        if("admin".equals(username))
        {
            credentials="ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";
        }else if("user".equals(username))
        {
            credentials="073d4c3ae812935f23cb3f2a71943f49e082a718";
        }
        //<3.realName:当前realm对象的name,调用父类对象的getName()方法即可
        String realmName=getName();
        //<4 盐值 这个盐值要唯一,我们假设这里用户名是唯一的,我们使用用户名作为盐值
        //盐值的作用:如果两个人的密码一样的话,就要盐值,就像西红柿,家不同的盐味道不一样!
        ByteSource credentialsSalt=ByteSource.Util.bytes(username);
        SimpleAuthenticationInfo info=null;
        info=new SimpleAuthenticationInfo(principal,credentials,credentialsSalt,realmName);
        return info;
    }

    public static void main(String[] args) {
        String algorithmName="SHA1";
        Object credentials="123456";
        Object salt=ByteSource.Util.bytes("admin");
        int hashIterations=1024;
        Object result = new SimpleHash(algorithmName, credentials, 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"></property>-->
        <!--有多个就使用下面这个-->
        <property name="authenticator" ref="authenticator"></property>
          <property name="realms">
            <list>
                <ref bean="jdbcRealm"></ref>
                <ref bean="secondRealm"></ref>
            </list>
        </property>
    </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">
      
        <!--修改认证策略,这里为所有都ok才ok!-->
        <property name="authenticationStrategy">
            <bean class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean>
        </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 直接配置实现了 org.apache.shiro.realm.Realm 接口的 bean
    -->
    <bean id="jdbcRealm" class="com.atguigu.shiro.realms.ShiroRealm">
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="MD5"></property>
                <property name="hashIterations" value="1024"></property>
            </bean>
        </property>
    </bean>
    <bean id="secondRealm" class="com.atguigu.shiro.realms.SecondRealm">
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <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.
    -->
    <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 登出.
        	4). roles 角色过滤器
        -->

        <property name="filterChainDefinitions">
            <value>
                /login.jsp = anon
                /shiro/login = anon
                /shiro/logout = logout
                # everything else requires authentication:
                /** = authc
            </value>
        </property>
    </bean>


</beans>

这样就ok了。

发布了241 篇原创文章 · 获赞 94 · 访问量 13万+

猜你喜欢

转载自blog.csdn.net/weixin_41060905/article/details/100170540