这里我给出配置shiro的所以步骤
如果用的是Maven,关于所有shiro需要的jar包的pom.xml就是
<properties>
<hibernate.version>4.3.8.Final</hibernate.version>
<spring.version>4.1.4.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<shiro.version>1.2.3</shiro.version>
</properties>
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</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-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
加载完Maven install后正式开始配置项目
在项目的web.xml下增加以下内容,Shiro的过滤器配置(如果没有这个,Shiro是不会处理请求的)
<!-- Shiro的配置 -->
<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>
创建spring-shiro.xml,内容为
spring-shiro.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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd"
default-lazy-init="true">
<description>shiro的安全配置</description>
<!-- <context:property-placeholder location="classpath:redis.properties"/> -->
<!-- Shiro's main business-tier object for web-enabled applications -->
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm" />
</bean>
<!-- 項目自定义的Realm-->
<bean id="myRealm" class="com.usersAc.realm.MyRealm">
<!-- <property name="userService" ref="userServiceImpl"/> -->
</bean>
<!-- Shiro Filter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 配置安全管理器 -->
<property name="securityManager" ref="securityManager" />
<!-- 登录失败跳转 -->
<property name="loginUrl" value="/userrelog.action" />
<!-- < property name="successUrl" value="/" /> -->
<!-- 权限验证失败跳转 -->
<property name="unauthorizedUrl" value="/error.jsp" />
<!-- shiro约束配置 -->
<property name="filterChainDefinitions">
<!--
anon匿名使用
roles[admin]需要有admin权限才能访问
authc需要身份认证才能访问
user则表示访问该地址的用户是身份验证通过或RememberMe登录的都可以
-->
<value>
/Slogin.action = anon
/userlogout!logout.action = logout
<!-- /js/** = anon -->
/O_*=user
/A_* = authc,roles[admin]
<!-- /admin_** = authc,roles[admin] -->
</value>
</property>
</bean>
<!--配置bean的后置处理器来自动调用Shiro中的bean的init和destroy方法。 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
<!--配置使shiro注解起作用的bean,需要放在 lifecycleBeanPostProcessor后面 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"></bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager"></property>
</bean>
我自己的项目(com.usersAc.realm)的包下创建自定义的Realm---MyRealm.java,最后路径一定要和
<bean id="myRealm" class="com.usersAc.realm.MyRealm">
</bean>
是一致的,不然找不到你的Realm
MyRealm.java
package com.usersAc.realm;
import java.security.MessageDigest;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import com.usersAc.entity.SirenesUser;
import com.usersAc.service.UserService;
/*AuthorizingRealm*/
/*FormAuthenticationFilter*/
/*ModularRealmAuthenticator
*
* // 判断getRealms()是否返回为空
* assertRealmsConfigured();
* */
public class MyRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {//权限验证方法
// TODO Auto-generated method stub
System.out.println("进入权限验证");
String username=arg0.getPrimaryPrincipal().toString();
Set<String> roles=userService.findRoleByName(username);
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(roles);
System.out.println("验证中");
/*
* 此处从Service获取数据库关于此用户的角色
*/
//info.setRoles(roles);
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {//身份验证方法
// TODO Auto-generated method stub
System.out.println("进入登录认证");
UsernamePasswordToken token=(UsernamePasswordToken) arg0;
String username=token.getUsername();
String password=new String(token.getPassword());
SirenesUser user=userService.findUserByName(username);/*从数据库以用户名为参数取出User对象*/
if(password!=null&&!"".equals(password)){
if(password.equals(user.getPassword())){ /*user.getPassword()获取这个用户的密码*/
System.out.println("验证成功");
AuthenticationInfo authInfo=new SimpleAuthenticationInfo(user.getUserName(),password,"user");
return authInfo;
}
}
/*需要加个盐值加密的话,改为*//*if(user!=null){String salt=user.getPSalt();salt=md5Hex(salt+user.getUserId());String hexpassword=md5Hex(password+salt);System.out.println("加密后密码:"+hexpassword);if(password!=null&&!"".equals(password)){if(hexpassword.equals(user.getPassword())){System.out.println("验证成功");AuthenticationInfo authInfo=new SimpleAuthenticationInfo(user.getUserName(),password,ByteSource.Util.bytes(salt),"user");return authInfo;}}}*///throw new ShiroException("用户名和密码不存在");//return null;throw new UnknownAccountException();}public static String md5Hex(String src) { try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[] bs = md5.digest(src.getBytes()); return new String(new Hex().encode(bs)); } catch (Exception e) { return null; } } }
如果我们要使用Realm,则在Action定义一个方法
@Action(value="Slogin",results={
@Result(name=SUCCESS,location="Jump",type="chain"),
@Result(name=ERROR,location="userrelog",type="chain")
})
public String loginByShiro(){ /*这里我用了注解的方式去配置struts,Action名为Slogin*/
ActionContext actionContext=ActionContext.getContext();
System.out.println("使用shiro");
String usern = map.get("username"); /*这里是从前台发过来的请求中获取Username和Password,可以自定义*/
String passd = map.get("password");
Subject subject=SecurityUtils.getSubject(); /*创建subject*/
UsernamePasswordToken token=new UsernamePasswordToken(usern,passd);/*创建一个token*/
try{
//token.setRememberMe(true);
subject.login(token); /*subject调用login后会到MyRealm验证*/
this.loginMessage(actionContext, usern);
return SUCCESS;
}catch(UnknownAccountException e){
System.out.println("用户名或密码错误");
addActionMessage("用户名或密码错误");
return ERROR;
}
/*String exceptionClassName = (String) request.get("shiroLoginFailure");
//根据Shiro返回的异常类信息判断,抛出并处理这个异常信息
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户不存在,请核对用户名";//如果UnknownAccountException抛出这个异常,表示账号不存在
} else if (IncorrectCredentialsException.class.getName().equals(
exceptionClassName)) {
error = "用户名/密码错误";
} else if (exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
} */
}
好了,现在基本配置完成,可以测试登录了
这个只是基本配置,如果要使用EhCache缓存还可以用
spring-shiro.xml
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm" />
<property name="cacheManager" ref="cacheManager" />
</bean>
<!-- 缓存管理器:用户授权信息Cache, 采用EhCache -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
</bean>
shiro-ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">
<diskStore path="java.io.tmpdir"/>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统当机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。
memoryStoreEvictionPolicy:
Ehcache的三种清空策略;
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
/>
<!-- 登录记录缓存锁定10分钟 -->
<cache name="passwordRetryCache"
maxEntriesLocalHeap="2000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="0"
overflowToDisk="false"
statistics="true">
</cache>
</ehcache>