一、前言
上一章节通过注解和缓存做了权限验证,这里增加验证码与记住登录功能。注意:shiro缓存是权限授权的缓存。
二、验证码
2.1编写继承FormAuthenticationFilter的权限验证自定义类
重写一个验证验证码的onAccessDenied方法
CustomFormAuthenticationFilter.java
package com.ycy.shiro; import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * */ public class CustomFormAuthenticationFilter extends FormAuthenticationFilter { @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { // 校验验证码 // 从session获取正确的验证码 HttpSession session = ((HttpServletRequest)request).getSession(); //页面输入的验证码 String randomcode = request.getParameter("randomcode"); //从session中取出验证码 String validateCode = (String) session.getAttribute("validateCode"); if (randomcode!=null&&validateCode!=null&&!randomcode.equals(validateCode)) { // randomCodeError表示验证码错误 request.setAttribute("shiroLoginFailure", "randomCodeError"); //拒绝访问,不再校验账号和密码 return true; } return super.onAccessDenied(request, response, mappedValue); } }
2.2 登录获取我们自定义验证
package com.ycy.controller; import com.ycy.Exception.CustomException; import com.ycy.model.ActiveUser; import com.ycy.service.SysService; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; /** * * <p>Title: LoginController</p> * <p>Description: 登陆和退出</p> */ @Controller public class LoginController { @Autowired private SysService sysService; //用户登陆提交方法 @RequestMapping("/login") public String login(HttpServletRequest request)throws Exception{ //如果登录失败从request中获取认证异常信息,shrioLoginFailure就是shiro异常类的全限定名 String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); //根据shrio返回的异常路径判断,抛出指定异常信息 if (exceptionClassName!=null){ if(UnknownAccountException.class.getName().equals(exceptionClassName)){ //抛出异常 throw new CustomException("账户不存在"); }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){ throw new CustomException("用户名/密码错误"); }else if("randomCodeError".equals(exceptionClassName)){ throw new CustomException("验证码错误"); } else { throw new Exception("未知错误"); } } return "login"; } }
2.3 注入自定义的FormAuthenticationFilter
在applicationContext中注入我们自己定义的验证器
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd "> <!-- Shiro 的Web过滤器 --> <!--================================================1、与web.xml对应的bean===================================--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 如果没有认证将要跳转的登陆地址,http可访问的url,如果不在表单认证过虑器FormAuthenticationFilter中指定此地址就为身份认证地址 --> <property name="loginUrl" value="/login" /> <!-- 没有权限跳转的地址 --> <property name="unauthorizedUrl" value="/pages/jsp/refuse.jsp" /> <!-- 自定义filter配置 --> <property name="filters"> <map> <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中--> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> <!--过滤定义,从上而下,蒋匿名的anon放最下面--> <property name="filterChainDefinitions"> <value> <!--静态资源通过--> /js/** anon /images/** anon /styles/** anon <!-- 验证码,可匿名访问 --> /pages/jsp/validatecode.jsp = anon <!--商品查询需要商品查询权限(权限表达式)尽量有注解--> <!--/items/queryItems=perms[item:query]--> <!--表示所有请求url必须通过认证--> /**= authc <!--请求logout,shrio擦除sssion--> /logout=logout <!--表示所有url都可以通过--> <!-- /** anon--> </value> </property> </bean> <!-- ==============================================2、安全管理器============================================== --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <!--缓存管理--> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 缓存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:cache/ehcache.xml"/> </bean> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效时长,单位毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 删除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean> <!-- 自定义form认证过虑器 --> <!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --> <bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter"> <!--表单中账户和密码的input框名称--> <property name="usernameParam" value="username"/> <property name="passwordParam" value="password"/> </bean> <!--==============================================3、realm===================================================--> <!-- Shiro配置,继承自AuthorizingRealm的自定义Realm (解决初始化时的依赖循环问题,通过这里向realm中注入userservice实现)--> <bean id="userRealm" class="com.ycy.shiro.CustomRealm" > <property name="authorizationCacheName" value="authorizationcache" /> <property name="credentialsMatcher" ref="credentialsMatcher" /> </bean> <!--4 凭证匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5" /> <property name="hashIterations" value="1" /> </bean> </beans>
2.4 在页面编写验证码
<TR> <TD>验证码:</TD> <TD><input id="randomcode" name="randomcode" size="8" /> <img id="randomcode_img" alt="" width="56" height="20" align='absMiddle' src="${baseurl}pages/jsp/validatecode.jsp" onclick="randomcode_refresh()"/> <a href=javascript:randomcode_refresh()>刷新</a></TD> </TR>
2.5 设置验证码能够匿名访问
<value> <!--静态资源通过--> /js/** anon /images/** anon /styles/** anon <!-- 验证码,可匿名访问 --> /pages/jsp/validatecode.jsp = anon <!--请求logout,shrio擦除sssion--> /logout=logout <!--商品查询需要商品查询权限(权限表达式)尽量有注解--> <!--/items/queryItems=perms[item:query]--> <!--表示所有请求url必须通过认证--> /**= authc <!--表示所有url都可以通过--> <!-- /** anon--> </value> </property>
三、记住登录设置
就是写入cookie,shrio本身就支持。
1、用户序列号
public class SysPermission implements Serializable{ private Long id; private String name; private String type; private String url; private String percode; private Long parentid;
2、记住登录xml配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd "> <!-- Shiro 的Web过滤器 --> <!--================================================1、与web.xml对应的bean===================================--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 如果没有认证将要跳转的登陆地址,http可访问的url,如果不在表单认证过虑器FormAuthenticationFilter中指定此地址就为身份认证地址 --> <property name="loginUrl" value="/login" /> <!-- 没有权限跳转的地址 --> <property name="unauthorizedUrl" value="/pages/jsp/refuse.jsp" /> <!-- 自定义filter配置 --> <property name="filters"> <map> <!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中--> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> <!--过滤定义,从上而下,蒋匿名的anon放最下面--> <property name="filterChainDefinitions"> <value> <!--静态资源通过--> /js/** anon /images/** anon /styles/** anon <!-- 验证码,可匿名访问 --> /pages/jsp/validatecode.jsp = anon <!--请求logout,shrio擦除sssion--> /logout=logout <!--商品查询需要商品查询权限(权限表达式)尽量有注解--> <!--/items/queryItems=perms[item:query]--> <!-- 配置记住我或认证通过可以访问的地址 --> /index.jsp = user /first = user /welcome.jsp = user <!--表示所有请求url必须通过认证--> /**= authc <!--表示所有url都可以通过--> <!-- /** anon--> </value> </property> </bean> <!-- ==============================================2、安全管理器============================================== --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <!--缓存管理--> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager"/> <!-- 记住我 --> <property name="rememberMeManager" ref="rememberMeManager"/> </bean> <!-- 缓存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManagerConfigFile" value="classpath:cache/ehcache.xml"/> </bean> <!-- 会话管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效时长,单位毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 删除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean> <!-- 自定义form认证过虑器 --> <!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 --> <bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter"> <!--表单中账户和密码的input框名称--> <property name="usernameParam" value="username"/> <property name="passwordParam" value="password"/> <property name="rememberMeParam" value="rememberMe"/> </bean> <!--==============================================3、realm===================================================--> <!-- Shiro配置,继承自AuthorizingRealm的自定义Realm (解决初始化时的依赖循环问题,通过这里向realm中注入userservice实现)--> <bean id="userRealm" class="com.ycy.shiro.CustomRealm" > <property name="authorizationCacheName" value="authorizationcache" /> <property name="credentialsMatcher" ref="credentialsMatcher" /> </bean> <!--4 凭证匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5" /> <property name="hashIterations" value="1" /> </bean> <!--==============================================rememberMeManager管理器========================================--> <!-- rememberMeManager管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 记住我cookie --> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <!-- 记住我cookie生效时间30天 --> <property name="maxAge" value="2592000" /> </bean> </beans>
1其中记住登录为
<!--==============================================rememberMeManager管理器========================================--> <!-- rememberMeManager管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 记住我cookie --> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <!-- 记住我cookie生效时间30天 --> <property name="maxAge" value="2592000" /> </bean>
2需要加入securityManager
<!-- 记住我 --> <property name="rememberMeManager" ref="rememberMeManager"/>
3获取记住我的input属性
<bean id="formAuthenticationFilter" class="com.ycy.shiro.CustomFormAuthenticationFilter"> <!--表单中账户和密码的input框名称--> <property name="usernameParam" value="username"/> <property name="passwordParam" value="password"/> <!--记住我input框名称--> <property name="rememberMeParam" value="rememberMe"/> </bean>
3、登录页面设置
<TR> <TD></TD> <TD> <input type="checkbox" name="rememberMe" />自动登陆 </TD> </TR>
4、测试记住登录
查询cookie是否有我们的记录,而且可以查询cookie用户页面,用到另一个过滤器 user。在securityManager配置过滤器
<!-- 配置记住我或认证通过可以访问的地址 --> /index.jsp = user /first = user /welcome.jsp = user
如图:可以访问欢迎页面,不能访问商品管理页面。
总结记住登录:设置记住登录管理器====注入securityManager=======设置input=============设置选择框name属性==========设置user拦截器访问页面
user拦截器“
user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查
---------摘录自ycy博文
感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程