浏览 3254 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-08-25
一般来说,登录时都会要求用户输入验证码,以防止恶意登录。 可是,SpringSecurity并没有为我们提供这样的功能,所以就需要我们自己来解决了。 那么该如何解决呢,其实也挺简单的, 核对验证码信息,当然是在登录时处理的,所以,使用filter是最佳选择。
既然确定了方向,那么久该考虑如何增加这个filter了,其实可以有两种方案: 1.继承UsernamePasswordAuthenticationFilter ,在里面增加验证码验证规则即可; 2.自己定义一个filter,专门处理验证码验证;
笔者这里推荐使用第二种方案,因为第一种我们需要显示声明login-filter,所以需要修改SpringSecurity的配置文件,而方案2根本不需要修改,只需要向一般的filter一样,在web.xml中增加配置即可,唯一需要注意的是,mapping一定要与触发login-filter的url一致,如下所示: <filter> <filter-name>imageFilter</filter-name> <filter-class>com.piaoyi.common.filter.ImageFilter</filter-class> </filter> <filter-mapping> <filter-name>imageFilter</filter-name> <url-pattern>/j_spring_security_check</url-pattern> </filter-mapping> 另外需要注意的是,该filter的mapping一定要声明在springSecurityFilterChain的mapping之前,这样可以保证请求先被imageFilter处理。
设计思路就是这样的,这里给出一个简单的实现。
login.jsp <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ include file="/WEB-INF/views/jsp/common/includes.jsp"%> <!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=UTF-8"> <title>登陆</title> </head> <body> <center> <div class="error"> ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message }</div> <form name='f' id='f' action='<%=request.getContextPath()%>/j_spring_security_check' method='POST'> <table style="width: 50%"> <tr> <td style="text-align: right; width: 35%">用户名称 :</td> <td style="text-align: left"><input type='text' name='j_username' value=''></td> </tr> <tr> <td style="text-align: right">密码 :</td> <td style="text-align: left"><input type='password' name='j_password' /></td> </tr> <tr> <td style="text-align: right"><label for="j_captcha"> 验证码: </label></td> <td> <input type='text' name='j_captcha' class="required" size='5' /> <img id="imageF" src="<c:url value="/resource/image.jsp"/>" /> <a href="#" id="flashImage">看不清楚换一张</a> </td> </tr> <tr> <td align="right"><input id="_spring_security_remember_me" name="_spring_security_remember_me" type="checkbox" value="true" /> </td> <td><label for="_spring_security_remember_me">Remember Me?</label> </td> </tr> <tr> <td colspan="2" style="text-align: center"><input type="submit" name="submit" value="登录" /></td> </tr> </table> </form> </center> <script type="text/javascript"> document.f.j_username.focus(); if ('${message}' == 1) { alert("用户名或密码错误"); } jQuery(function($){ $("#flashImage").click(function(){ $('#imageF').hide().attr('src','<c:url value="/resource/image.jsp"/>'+ '?'+ Math.floor(Math.random() * 100)).fadeIn(); }); }); </script> </body> </html> ImageFilter.java package com.piaoyi.common.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ImageFilter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { // TODO Auto-generated method stub HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; String yanzhengm = request.getParameter("j_captcha"); String sessionyanz = (String)request.getSession(true).getAttribute("yzkeyword"); if(yanzhengm.equals(sessionyanz)){ arg2.doFilter(request, response); }else{ response.sendRedirect("/login.do"); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } } image.jsp <%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" pageEncoding="UTF-8"%> <%! Color getRandColor(int fc,int bc){//随机获得颜色,RGB格式 Random random = new Random(); if(fc>255) fc=255; if(bc>255) bc=255; int r=fc+random.nextInt(bc-fc); int g=fc+random.nextInt(bc-fc); int b=fc+random.nextInt(bc-fc); return new Color(r,g,b); } %> <% //清除缓存,每次访问该页面时都从服务器端读取 response.setHeader("Pragma","No-cache"); response.setHeader("Cache-Control","no-cache"); response.setDateHeader("Expires", 0); // 定义显示图片的宽度和高度 int width=60, height=20; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 画图画板 Graphics g = image.getGraphics(); //定义一个随机数 Random random = new Random(); // 设置画板背景颜色 g.setColor(getRandColor(200,250)); //设置画板的填充范围 g.fillRect(0, 0, width, height); //设置字体 g.setFont(new Font("Times New Roman",Font.PLAIN,18)); // 设置线条颜色并画线,155条 g.setColor(getRandColor(160,200)); for (int i=0;i<155;i++) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(12); int yl = random.nextInt(12); g.drawLine(x,y,x+xl,y+yl); } // 显示数字,4位长度 String sRand=""; for (int i=0;i<4;i++){ String rand=String.valueOf(random.nextInt(10)); sRand+=rand; // 设置每个数字的颜色 g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110))); //在画板上写数字,起始位置 g.drawString(rand,13*i+6,16); } // 保存进session session.setAttribute("yzkeyword",sRand); //System.out.println("yzm:"+sRand); // 显示图片 g.dispose(); %> <% //转换成一张图片,格式为JPEG ImageIO.write(image, "JPEG", response.getOutputStream()); out.clear();//清空缓存的内容。 pageContext.pushBody(); %> applicationContext-security.xml <?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tool="http://www.springframework.org/schema/tool" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd" default-lazy-init="true"> <http security="none" pattern="/index.do" /> <http auto-config='true' access-decision-manager-ref="accessDecisionManager" access-denied-page="/index.do"> <intercept-url pattern="/demo.do*" access="IS_AUTHENTICATED_REMEMBERED" /> <intercept-url pattern="/**/*.do*" access="HODLE" /> <logout logout-url="/logout.do" invalidate-session="true" logout-success-url="/logout.jsp" /> <form-login login-page="/index.do" default-target-url="/frame.do" always-use-default-target="true" authentication-failure-url="/index.do?login_error=1" /> <session-management> <concurrency-control max-sessions="1" expired-url="/timeout.jsp"/> </session-management> <remember-me key="jbcpPetStore" /> </http> <!-- Automatically receives AuthenticationEvent messages --> <beans:bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener" /> <authentication-manager erase-credentials="false"> <authentication-provider user-service-ref="userService"> <password-encoder hash="md5" /> </authentication-provider> </authentication-manager> <beans:bean id="userService" class="com.piaoyi.common.security.UserService" /> <beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased"> <beans:property name="decisionVoters"> <beans:list> <beans:bean class="org.springframework.security.access.vote.RoleVoter" /> <beans:bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> <beans:bean class="com.piaoyi.common.security.DynamicRoleVoter" /> </beans:list> </beans:property> </beans:bean> </beans:beans> 效果图如下:
另外,从网上也看到了类似的解决方案:http://liukai.iteye.com/category/140288?show_full=true 里面使用到了jcaptcha的jar包,我整合后发现也很好用,附件中给出jar包。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |