版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37358860/article/details/89242495
ssm框架集成shiro管理用户登录------简单点
一. 首先你得有个ssm框架能够实现最简单的用户登录验证.
简单的maven构建ssm框架实现用户登录验证源码地址(maven3.5+jdk1.8)
二.将shiro集成到ssm框架中
- 在pom.xml文件中添加shiro依赖
<!-- shiro start -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.4</version>
</dependency>
<!-- shiro end -->
- web.xml中配置shiro过滤器
<!-- 配置shiro的过滤器 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
- 在spring配置文件中配置shiro
<!-- 配置shiro框架的过滤器工厂bean -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<!-- 登录项目首次访问的地址 -->
<property name="loginUrl" value="/index.jsp" />
<property name="successUrl" value="/successUrl.jsp" />
<property name="unauthorizedUrl" value="/unauthorizedUrl.jsp" />
<!-- 指定URL拦截策略 ,静态资源放行,登录放行,其他的需要认证也就是登录-->
<property name="filterChainDefinitions">
<value>
/index.jsp=anon
/jsp/error.jsp=anon
/login/loginPage.action=anon
/**=authc
</value>
</property>
</bean>
<!-- 配置安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="MyRealm" />
<!-- 注入缓存管理器 -->
<property name="cacheManager" ref="cacheManager" />
</bean>
<!-- 注册自定义realm -->
<bean id="MyRealm"
class="com.lgf.maven_ssm.shiro.MyRealm" />
<!-- 注册缓存管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<!-- 注入ehcache配置文件 -->
<property name="cacheManagerConfigFile" value="classpath:/ehcache_shiro.xml" />
</bean>
安全管理器中的realm和cacheManager是我们自己配置的
- 创建自定义realm类, MyRealm
package com.lgf.maven_ssm.shiro;
import javax.annotation.Resource;
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.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.lgf.maven_ssm.system.entity.CsdnUser;
import com.lgf.maven_ssm.system.service.ILoginService;
public class MyRealm extends AuthorizingRealm {
@Resource
private ILoginService loginService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
CsdnUser user=loginService.getUserByName(userToken.getUsername());
if (user != null){
// 若存在,将此用户存放到登录认证 info 中,无需自己做密码对比,Shiro 会为我们进行密码对比校验
return new SimpleAuthenticationInfo(user, user.getUserPassword(), getName());
}
return null;
}
}
- 创建shiro缓存的配置文件ehcache_shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">
<!--
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>
三.在登录验证控制器中使用shiro进行管理用户登录
- 将原来的登录验证代码替换成以下代码
// 验证
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getUserPassword());
Subject currentUser = SecurityUtils.getSubject();// 获取当前的 Subject
try {
// 在调用了 login 方法后, SecurityManager 会收到 AuthenticationToken, 并将其发送给已配置的 Realm 执行必须的认证检查
// 每个 Realm 都能在必要时对提交的 AuthenticationTokens 作出反应
// 所以这一步在调用 login(token) 方法时, 它会走到 MyRealm.doGetAuthenticationInfo() 方法中, 具体验证方式详见此方法
currentUser.login(token);
}catch(UnknownAccountException uae){
System.err.println("进行登录验证.. 验证未通过, 未知账户");
}catch(IncorrectCredentialsException ice){
System.err.println("进行登录验证.. 验证未通过, 错误的凭证");
}catch(LockedAccountException lae){
System.err.println("对用户 进行登录验证.. 验证未通过, 账户已锁定");
}catch(ExcessiveAttemptsException eae){
System.err.println("对用户进行登录验证.. 验证未通过, 错误次数大于 5 次, 账户已锁定");
}catch (DisabledAccountException sae){
System.err.println("对用户进行登录验证.. 验证未通过, 帐号已经禁止登录");
}catch(AuthenticationException ae){
System.err.println("对用户 进行登录验证.. 验证未通过, 堆栈轨迹如下");
ae.printStackTrace();
}
// 验证是否登录成功
if(currentUser.isAuthenticated()){//登录成功
return "jsp/sys/login";
}else {//登录失败
token.clear();
return "jsp/error";
}