参考文档: http://tool.oschina.net/apidocs/apidoc?api=shiro-core-1.2.0 https://www.cnblogs.com/learnhow/p/5694876.html pom.xml配置: ``` <!-- shiro配置start --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.2</version> </dependency> <!-- 用这一个版本 不然会报 Another CacheManager with same name '' already exists in the same VM --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.4.8</version> </dependency> <!-- shiro配置end --> ``` web.xml配置: ``` <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1" metadata-complete="true"> <servlet > <servlet-name>DispatcherServlet</servlet-name > <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param> <param-name>contextConfigLocation</param-name > <param-value>classpath:spring/spring-*.xml</param-value > </init-param> </servlet> <servlet-mapping> <servlet-name>DispatcherServlet</servlet-name > <url-pattern>*.do</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <!-- 读取Spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> <!-- classpath:mybatis-config.xml --> classpath:spring/spring-*.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- shiro配置 开始 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <async-supported>true</async-supported> <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> <!-- shiro配置 结束 --> <error-page> <error-code>404</error-code> <location>/errorPage/404.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/errorPage/500.jsp</location> </error-page> </web-app> ``` spring-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" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 缓存管理器 使用Ehcache实现 --> <bean id="cachManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" > <property name="cacheManagerConfigFile" value="classpath:ecache.xml" /> </bean> <!-- 配置凭证 --> <bean id="credentialsMatcher" class="com.soecode.lyf.shiro.RetryLimitHashedCredentialsMatcher" > <constructor-arg ref="cachManager" /> <!-- 加密方式 --> <property name="hashAlgorithmName" value="md5" /> <!-- 加密次数 --> <property name="hashIterations" value="50" /> <!-- 存储的凭据十六进制编码 --> <property name="storedCredentialsHexEncoded" value="true" /> </bean> <!-- Realm实现 --> <bean id="userRealm" class="com.soecode.lyf.shiro.UserRealm"> <property name="credentialsMatcher" ref="credentialsMatcher" /> </bean> <!-- 安全管理器 --> <bean id = "securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" > <property name="realm" ref="userRealm" /> </bean> <!-- shiro过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" > <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/" /> <property name="unauthorizedUrl" value="/" /> <property name="filterChainDefinitions"> <value> <!-- anon 无参,表示可匿名使用,可以理解为匿名用户或游客 authc 无参,表示需认证才能使用 authc,roles[admin] 表示用户必需已通过认证,并拥有admin角色才可以正常发起'/admin'请求 --> <!-- /admin = authc,roles[admin] --> /static/** = anon /** = anon </value> </property> </bean> <!-- 设置生命周期 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:shared="true"/> </beans> ``` ecache.xml配置如下: ``` <?xml version="1.0" encoding="UTF-8"?> <ehcache updateCheck="false" name="shirocache"> <diskStore path="java.io.tmpdir" /> <!-- name 缓存名称 maxElementsInMemory:缓存最大个数 eternal:对象是否永久有效,一但设置了,timeout将不起作用 timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性, 默认值是0,也就是可闲置时间无穷大 timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false 对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大 overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中 --> <!-- maxEntriesLocalHeap="2000" 无效--> <cache name="passwordRetryCache" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="0" overflowToDisk="false" statistics="true"> </cache> </ehcache> ``` ShiroTest.java用于获得md5加密后的密码用于测试,密码不能解密的话会报错所以密码不能随意添加: ``` public static void main(String[] args) { String hashAlgorithmName = "MD5"; String credentials = "1"; int hashIterations = 50; Object obj = new SimpleHash(hashAlgorithmName, credentials, null, hashIterations); System.out.println(obj); } ``` UserRealm.java代码如下: ``` package com.soecode.lyf.shiro; import java.util.HashSet; import java.util.Set; 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.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; 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.soecode.lyf.entity.IUser; import com.soecode.lyf.service.IUserService; public class UserRealm extends AuthorizingRealm { @Autowired private IUserService iUserService; /** * 提供用户信息返回权限信息 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName = (String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //设置当前用户拥有的角色 Set<String> roles = new HashSet<String>(); roles.add("r1"); roles.add("r2"); //加入角色名 authorizationInfo.setRoles(roles); //设置当前用户的权限 Set<String> permissionNames = new HashSet<String>(); permissionNames.add("add"); permissionNames.add("view"); authorizationInfo.setStringPermissions(permissionNames); return authorizationInfo; } /** * 提供账户信息返回认证信息 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName = (String)token.getPrincipal(); IUser iUser = iUserService.findByUsername(userName); if(iUser==null){ //用户不存在 throw new UnknownAccountException(); } // if(iUser.getLocked()=1){ // throw new LockedAccountException(); // } // iUser.setPassword("003d75ffdd78e6469723594eae0e21aa"); SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(iUser.getLoginUser(), iUser.getPassword(), getName()); return simpleAuthenticationInfo; } } ``` RetryLimitHashedCredentialsMatcher.java的代码如下: ``` package com.soecode.lyf.shiro; import java.util.concurrent.atomic.AtomicInteger; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; /** * 匹配用户登录使用的令牌和数据库中保存的用户信息是否匹配 * @author an * */ public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { static{ System.out.println(">>>>>>>>>>>RetryLimitHashedCredentialsMatcher<<<<<<<<<<<"); } //声明一个缓存接口 private Cache<String,AtomicInteger> cache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager){ cache=cacheManager.getCache("passwordRetryCache"); } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); AtomicInteger retryCount = cache.get(username); if(retryCount == null){ retryCount = new AtomicInteger(0); cache.put(username, retryCount); } if(retryCount.incrementAndGet()>5){ throw new ExcessiveAttemptsException(); } boolean match = super.doCredentialsMatch(token, info); if(match){ cache.remove(username); } return match; } } ``` IUserController.java的代码如下: ``` package com.soecode.lyf.web; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import com.soecode.lyf.entity.IUser; import com.soecode.lyf.service.IUserService; import com.soecode.lyf.util.StringUtils; @Controller @RequestMapping("/main") public class IUserController { Logger logger = Logger.getLogger(IUserController.class); private static final String main_page="main"; private static final String index_page="main"; @Resource private IUserService iUserService; @Autowired private HttpSession session; @Autowired private SecurityManager securityManager; @RequestMapping("/toMainPage.do") public ModelAndView toMainPage(String loginUser,String password,HttpServletRequest request){ ModelAndView mv = new ModelAndView(); mv.setViewName("index"); UsernamePasswordToken token = new UsernamePasswordToken(loginUser,password); //记住我 // token.setRememberMe(true); Subject subject = SecurityUtils.getSubject(); String userName = (String)subject.getSession().getAttribute("userName"); if(!StringUtils.isBlank(userName)){ mv.setViewName(main_page); return mv; } try { subject.login(token); } catch (IncorrectCredentialsException ice) { // 捕获密码错误异常 mv.addObject("message", "密码错误!"); return mv; } catch (UnknownAccountException uae) { // 捕获未知用户名异常 mv.addObject("message", "登录名错误!"); return mv; } catch (ExcessiveAttemptsException eae) { // 捕获错误登录过多的异常 mv.addObject("message", "登录失败超过五次,暂时无法登录!"); return mv; } IUser user = iUserService.findByUsername(loginUser); request.getSession().setAttribute("userName", user.getUserName()); logger.debug("进入跳转的方法"); mv.setViewName(main_page); return mv; } /** * 登出 */ @RequestMapping("/logout.do") public ModelAndView logout(){ Subject subject = SecurityUtils.getSubject(); if(subject.isAuthenticated()){ subject.logout(); } ModelAndView mv = new ModelAndView(); mv.setViewName("index"); return mv; } } ``` main.jsp代码如下: ``` <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <h1>这里是首页</h1> <h2>欢迎:${userName}</h2> <shiro:hasRole name="r1"> 用户[<shiro:principal/>]拥有角色r1<br/> </shiro:hasRole> <shiro:hasRole name="r3"> 用户[<shiro:principal/>]拥有角色r3<br/> </shiro:hasRole> </body> </html> ```
转载于:https://my.oschina.net/u/3170610/blog/1818768