Spring + SpringMVC + Mybatis + Shiro 整合(下)

    上篇将ssm框架整合完毕,这里剩下最后一步整合shiro权限框架,其实权限拦截比较简单,我比较偏向于自己去写filter和servlet去完成权限的分配,因为能用一个类解决的问题就不要用一个jar包解决。不过可以先理解shiro的思想,然后自己去写类进行拦截,其实权限控制一个filter类加一个servlet就可以完成,完全不需要一个shiro,大家可以试试,后续会上传我写的权限控制类

第一步:导入shiro的jar包


        <!--Shiro Start-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <!--缓存-->
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>${ehcache.version}</version>
        </dependency>
        <!--Shiro End-->

shiro的版本用的是,看图

102007_Gv5u_3017023.png

第二步:整合spring和shiro

1.  新建一个spring-shiro.xml文件,内容如下

    关于shiro的内容这里就不多讲了,后续也会陆续上线shiro部分的博文,我这里有shiro的完整教学视频,需要的留下邮箱,我会发过去,免费,如果收费请拒绝支付,然后留言联系博主,谢谢。

<?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 配置-->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="cacheManager" ref="cacheManager"></property>
		<!-- 必须放在realms的前面配置,否则realms不生效 -->
		<property name="authenticator" ref="authenticator"></property>
		<property name="realms">
			<list>
				<ref bean="myRealm"/>
				<ref bean="myRealm2"/>
			</list>
		</property>
	</bean>
	
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<!-- <property name="cacheManager" ref="ehCacheManager"></property> -->
		<property name="cacheManagerConfigFile" value="classpath:config/ehcache.xml"/>
	</bean>
	
	<bean id="myRealm" class="xin.sunzy.ssms.realm.MyRealm">
		<property name="credentialsMatcher">
			<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
				<property name="hashAlgorithmName" value="MD5"></property>
				<property name="hashIterations" value="1024"></property>
                <property name="storedCredentialsHexEncoded" value="true"/>
			</bean>
		</property>
	</bean>

	<bean id="myRealm2" class="xin.sunzy.ssms.realm.MyRealm2">
		<property name="credentialsMatcher">
			<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
				<property name="hashAlgorithmName" value="SHA1"></property>
                <property name="hashIterations" value="1024"/>
			</bean>
		</property>
	</bean>
	
	<!-- 	可以自定义调用配置在spring ioc容器中的shirobean的生命周期方法 -->
	<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
	
	<!-- 	在配置了生命周期lifecycleBeanPostProcessor,之后才可以使注解生效 -->
	<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

	<!-- 认证策略 -->
	<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
		<property name="authenticationStrategy">
			<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
		</property>
	</bean>
	
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager"></property>
		<property name="loginUrl" value="/login.jsp"></property>
		<property name="successUrl" value="/list.jsp"></property>
		<property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
        <property name="filterChainDefinitionMap" ref="filterChainDefinitionsMap"/>
	</bean>

    <bean id="filterChainDefinitionsMapBuilder" class="xin.sunzy.ssms.realm.FilterChainDefinitionsMapBuilder"></bean>
    <bean id="filterChainDefinitionsMap" factory-bean="filterChainDefinitionsMapBuilder" factory-method="filterChainDefinitionsMap"></bean>
</beans>

然后在web.xml文件中添加shiroFilter

    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    注意配置filter-name一定要和spring中shiro bean的ID保持一致,否则会找不到实例报错,我这里都是用的shiroFilter。

    然后新建一个realm类,我这里建了两个realm类是为了测试验证策略

package xin.sunzy.ssms.realm;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import xin.sunzy.ssms.entity.po.Permission;
import xin.sunzy.ssms.entity.po.Role;
import xin.sunzy.ssms.entity.po.User;
import xin.sunzy.ssms.service.intf.IUserService;

public class MyRealm extends AuthorizingRealm {

    private final Logger logger = LoggerFactory.getLogger(MyRealm.class);

    @Autowired
    private IUserService userService;

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)throws AuthenticationException {

		System.out.println("MyRealm   doGetAuthenticationInfo ********");
		
		//从token中获取username
		String username = ((UsernamePasswordToken)token).getUsername();
        try {
            //从数据库中获取实体
            User user  = userService.findByUsername(username);
            if(user==null){
                throw new AuthenticationException("MyRealm 未知的用户异常。。。");
            }
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),
                    ByteSource.Util.bytes(user.getCredentialsSalt()),getName());
            return authenticationInfo;
        } catch (Exception e) {
            logger.error("数据库操作异常");
            return null;
        }
	}
	
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        System.out.println("MyRealm ,开始授权,doGetAuthorizationInfo**********");
        User user = (User) principalCollection.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        for(Role role : user.getRoleList()){
            authorizationInfo.addRole(role.getRoleName());
            for (Permission p : role.getPermissionList()){
                authorizationInfo.addStringPermission(p.getPermission());
                authorizationInfo.addStringPermission(p.getOpsUrl());
            }
        }
        return authorizationInfo;
    }
}

    这个MyRealm2没有任何用处,大家可以在里面写自己的认证逻辑 

package xin.sunzy.ssms.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.AuthenticatingRealm;

public class MyRealm2 extends AuthenticatingRealm {
		@Override
		protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

			System.out.println("MyRealm2 doGetAuthenticationInfo *********");
			return null;
		}
}

    然后就是FilterChainDefinitionsMapBuilder,实例工厂方法类,在spring-shiro.xml文件中用到了的,用来创建拦截链的map,我这里只是静态的拦截,这里需要从数据库中读取拦截链然后添加到map中。

package xin.sunzy.ssms.realm;

import org.springframework.beans.factory.annotation.Autowired;
import xin.sunzy.ssms.entity.po.User;
import xin.sunzy.ssms.service.intf.IUserService;

import java.util.LinkedHashMap;

public class FilterChainDefinitionsMapBuilder {

    private static final String ANON = "anon";
    private static final String AUTHC = "authc";
    private static final String LOGOUT = "logout";
    private static final String USER = "user";

    @Autowired
    private IUserService userService;

    LinkedHashMap<String,Object> filterChainDefinitionsMap() throws Exception {

        User user = userService.findByUsername("sunzy");
        LinkedHashMap<String,Object> map = new LinkedHashMap<>();
        map.put("/favicon.ico",ANON);
        map.put("/login.jsp",ANON);
        map.put("/login",ANON);
        map.put("/toLogin",ANON);
        map.put("/logout",LOGOUT);
        map.put("/valid",ANON);
        map.put("/**",AUTHC);
        return map;
    }
}

在classpath/config下新建一个ehcache.xml缓存配置文件

<ehcache>

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"/>

</ehcache>

到此,shiro也就整合完成了

源码地址:http://git.oschina.net/sunknightzy/ssms

转载于:https://my.oschina.net/GinkGo/blog/1524467

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值