验证码和记住我的功能

发表时间:2018-03-20 10:09:09 浏览量( 16 ) 留言数( 0 )

学习目标:

1、了解验证码的使用

2、了解rememberme的使用


学习过程:

一、验证码

1、自定义FormAuthenticationFilter,在验证账号和名称之前校验验证码。

public class VerCodeFormAuthenticationFilter extends FormAuthenticationFilter {
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue)
			throws Exception {
		// 校验验证码
		// 从session获取正确的验证码
		HttpSession session = ((HttpServletRequest) request).getSession();
		// 页面输入的验证码
		String randomcode = request.getParameter("randomcode");
		// 从session中取出验证码
		String vercode = (String) session.getAttribute("vercode");
		if (vercode != null && randomcode != null && !vercode.equalsIgnoreCase(randomcode)) {
				// 如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
				request.setAttribute("shiroLoginFailure", "randomCodeError");
				// 拒绝访问,不再校验账号和密码
				return true;
		}
		return super.onAccessDenied(request, response, mappedValue);
	}
}

2、配置匿名访问

验证码部分代码:

@Controller
@RequestMapping("/")
public class VerifyCodeControl {
	@RequestMapping("/cerCode")
	public void getAuthCode(HttpServletRequest request, HttpServletResponse response, HttpSession session)
			throws IOException {
		response.setHeader("Pragma", "No-cache");
		response.setHeader("Cache-Control", "no-cache");
		response.setDateHeader("Expires", 0);
		response.setContentType("image/jpeg");

		// 生成随机字串
		String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
		// 存入会话session
		session.setAttribute("vercode", verifyCode.toLowerCase());
		// 生成图片
		int w = 168, h = 33;
		VerifyCodeUtils.outputImage(w, h, response.getOutputStream(), verifyCode);

	}

}

修改shiro的配置,验证码的路径不需要权限拦截

/cerCode.do = anon


3、FormAuthenticationFilter配置


<!-- 基于Form表单的身份验证过滤器,不配置将也会注册此过虑器,表单中的用户账号、密码及loginurl将采用默认值,建议配置 -->


	<bean id="verCodeFormAuthenticationFilter" class="com.shiro.myfilter.VerCodeFormAuthenticationFilter">
		<property name="usernameParam" value="usernamemy" />
		<property name="passwordParam" value="passwordmy" />
	</bean>

	<!-- Shiro 的Web过滤器 -->
	<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<property name="securityManager" ref="securityManager" />
		<!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
		<property name="loginUrl" value="/login.do" />
		<property name="unauthorizedUrl" value="/refuse.do" />
		<!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->

		<property name="filters">
			<map>
				<entry key="authc" value-ref="verCodeFormAuthenticationFilter" />
			</map>
		</property>
	......下面省略



3、登陆页面

添加验证码,注意名称默认就是randomcode

<TD>验证码:<input id="randomcode" name="randomcode" size="8" /> 
<img id="randomcode_img" src="cerCode.do"align='absMiddle' /></TD>


二、记住我

1、记住我的实现原理    

   用户登陆选择“自动登陆”本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆,使用身份验证和使用记住我的方式进行验证时不一样的,已办来说使用身份验证的安全性高一点。如果你的网站安全性要求比较高,建议还是使用身份验证。因为记住我的认证时把登陆信息保存在浏览器的cookie里面,如果你的电脑让别人用了,或者在其他人的电脑上面使用了记住我的功能,那么别人就可以随时登陆了。再有cookie也有给窃取的可能性。

   在shiro中,你可以通过方法判断subject.isAuthenticated()表示用户进行了身份验证登录的,即使有Subject.login进行了登录;subject.isRemembered():表示用户是通过记住我登录的;且两者二选一,即subject.isAuthenticated()==true,则subject.isRemembered()==false;反之一样。

    如果要自己做RememeberMe,需要在登录之前这样创建Token:UsernamePasswordToken(用户名,密码,是否记住我),如:

Subject subject = SecurityUtils.getSubject();  

UsernamePasswordToken token = new UsernamePasswordToken(username, password);  

token.setRememberMe(true);  

subject.login(token);   


   另外在权限也需要进行相关的修改

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
    ……  
    <property name="filterChainDefinitions">  
        <value>  
            /logout.do = logout  
	   <!-- 改成user,这样就可以使用rememberme访问了。 -->
	   /login.do = authc
	   /** = user
        </value>  
    </property>  
</bean>

  

    /authenticated.do = authc,如果使用authc表示访问该地址用户必须身份验证通过(Subject. isAuthenticated()==true);而“/** = user”中的user表示访问该地址的用户是身份验证通过或RememberMe登录的都可以。

    还有一个使用前提条件,如果使用了对象保存用户身份,该用户对象需要实现java.io.Serializable接口,因为需要序列化保存在前端的cookie中。

public class User implements java.io.Serializable {

	private String userId;//用户id
	private String loginName;// 用户账号
	private String userName;// 用户名称
	private String password;//用户密码
	private String salt;//盐

2、配置rememberMeManager

	
	<!-- 记住我cookie -->
	<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
	    <!-- cookie的名字 -->
		<constructor-arg value="javadayup_v_1"/>
		<property name="httpOnly" value="true"/> 
        <property name="maxAge" value="2592000"/><!-- 30天时间,记住我30天 -->
	</bean>
	<!-- rememberMeManager管理器 -->
	<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
		<property name="cookie" ref="rememberMeCookie" />
		 <!-- rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)-->
        <property name="cipherKey"
                  value="#{T(org.apache.shiro.codec.Base64).decode('sdfERT567s0KTA3Kprsdag==')}"/>
	</bean>
	

	<!-- 安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="myCustomRealm" />
		<property name="cacheManager" ref="cacheManager" />
		<property name="sessionManager" ref="sessionManager" />
		<!-- 记住我 -->
		<property name="rememberMeManager" ref="rememberMeManager"/>
	</bean>


3、FormAuthenticationFilter配置

修改formAuthenticationFitler添加页面中“记住我checkbox”的input名称,不用配置也可以,默认就是rememberMe

<bean id="formAuthenticationFilter"

class="cn.itcast.ssm.shiro.MyFormAuthenticationFilter">

<!-- 表单中账号的input名称 -->

<property name="usernameParam" value="usercode" />

<!-- 表单中密码的input名称 -->

<property name="passwordParam" value="password" />

<property name="rememberMeParam" value="rememberMe"/>

</bean>



4、登陆页面

在login.jsp中添加“记住我”checkbox。

<TR>
                 <TD>
						<input type="checkbox" name="rememberMe" />自动登陆
				 </TD>
                 </TR>