您的位置:首页 > 编程语言 > Java开发

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

2017-08-27 00:00 267 查看
摘要: 摘要: SSMS框架整合,最近一直用Spring Boot框架,简化了开发,但是Spring Boot也有很多的不习惯和所有的配置都需要编码,而且有些东西还会发生未知的错误,总之要能随心所欲的掌控Spring Boot,首先得把框架整合掌握,否则在Spring Boot中发生了错误都不知道怎么去排查

上篇将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的版本用的是,看图



第二步:整合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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Shiro