SpringSecurity3.X--验证码

  • 博客分类:
  • Spring
  • SpringSecurity

springspringsecurity

目录

SpringSecurity3.X--一个简单实现

SpringSecurity3.X--前台与后台登录认证

SpringSecurity3.X--remember-me

SpringSecurity3.X--验证码

 

 

一般来说,登录时都会要求用户输入验证码,以防止恶意登录。

可是,SpringSecurity并没有为我们提供这样的功能,所以就需要我们自己来解决了。

那么该如何解决呢,其实也挺简单的,

核对验证码信息,当然是在登录时处理的,所以,使用filter是最佳选择。

 

既然确定了方向,那么久该考虑如何增加这个filter了,其实可以有两种方案:

1.继承UsernamePasswordAuthenticationFilter ,在里面增加验证码验证规则即可;

2.自己定义一个filter,专门处理验证码验证;

 

笔者这里推荐使用第二种方案,因为第一种我们需要显示声明login-filter,所以需要修改SpringSecurity的配置文件,而方案2根本不需要修改,只需要向一般的filter一样,在web.xml中增加配置即可,唯一需要注意的是,mapping一定要与触发login-filter的url一致,如下所示:

Xml代码

spring mvc手机验证码后端登录_java

 

spring mvc手机验证码后端登录_spring mvc手机验证码后端登录_02


1. <filter>  
2.         <filter-name>imageFilter</filter-name>  
3.         <filter-class>com.piaoyi.common.filter.ImageFilter</filter-class>  
4.            
5.     </filter>  
6.     <filter-mapping>  
7.         <filter-name>imageFilter</filter-name>  
8.         <url-pattern>/j_spring_security_check</url-pattern>  
9.     </filter-mapping>  
<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>
		<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

Html代码

spring mvc手机验证码后端登录_java

 

spring mvc手机验证码后端登录_spring mvc手机验证码后端登录_02


<%@ 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>
<%@ 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>

1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
2.     pageEncoding="UTF-8"%>  
3. <%@ include file="/WEB-INF/views/jsp/common/includes.jsp"%>  
4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
5. <html>  
6. <head>  
7. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
8. <title>登陆</title>  
9. </head>  
10. <body>  
11.   
12.     <center>  
13.         <div class="error">  
14.             ${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message }</div>  
15.         <form name='f' id='f'  
16.             action='<%=request.getContextPath()%>/j_spring_security_check'  
17.             method='POST'>  
18.             <table style="width: 50%">  
19.                 <tr>  
20.                     <td style="text-align: right; width: 35%">用户名称 :</td>  
21.                     <td style="text-align: left"><input type='text'  
22.                         name='j_username' value=''></td>  
23.                 </tr>  
24.                 <tr>  
25.                     <td style="text-align: right">密码 :</td>  
26.                     <td style="text-align: left"><input type='password'  
27.                         name='j_password' /></td>  
28.                 </tr>  
29.                 <tr>  
30.                     <td style="text-align: right"><label for="j_captcha"> 验证码: </label></td>  
31.                     <td>  
32.                     <input type='text' name='j_captcha' class="required"  
33.                         size='5' />  
34.                         <img id="imageF" src="<c:url value="/resource/image.jsp"/>" />  
35.                     <a href="#" id="flashImage">看不清楚换一张</a>  
36.                        
37.                     </td>  
38.                 </tr>  
39.                 <tr>  
40.                     <td align="right"><input id="_spring_security_remember_me"  
41.                         name="_spring_security_remember_me" type="checkbox" value="true" />  
42.   
43.                     </td>  
44.                     <td><label for="_spring_security_remember_me">Remember Me?</label>  
45.                     </td>  
46.                 </tr>  
47.                 <tr>  
48.                     <td colspan="2" style="text-align: center"><input  
49.                         type="submit" name="submit" value="登录" /></td>  
50.                 </tr>  
51.             </table>  
52.         </form>  
53.     </center>  
54.     <script type="text/javascript">  
55.        
56.         document.f.j_username.focus();   
57.         if ('${message}' == 1) {   
58.             alert("用户名或密码错误");   
59.         }   
60.            
61.         jQuery(function($){   
62.                
63.        
64.             $("#flashImage").click(function(){   
65.                    
66.                 $('#imageF').hide().attr('src','<c:url value="/resource/image.jsp"/>'+ '?'+ Math.floor(Math.random() * 100)).fadeIn();   
67.             });   
68.         });   
69.            
70.            
71.     </script>  
72.   
73.   
74. </body>  
75. </html>

 ImageFilter.java

Java代码

spring mvc手机验证码后端登录_java

 

spring mvc手机验证码后端登录_spring mvc手机验证码后端登录_02


1. package com.piaoyi.common.filter;   
2.   
3. import java.io.IOException;   
4.   
5. import javax.servlet.Filter;   
6. import javax.servlet.FilterChain;   
7. import javax.servlet.FilterConfig;   
8. import javax.servlet.ServletException;   
9. import javax.servlet.ServletRequest;   
10. import javax.servlet.ServletResponse;   
11. import javax.servlet.http.HttpServletRequest;   
12. import javax.servlet.http.HttpServletResponse;   
13.   
14. public class ImageFilter implements Filter{   
15.   
16.     @Override  
17.     public void destroy() {   
18.         // TODO Auto-generated method stub   
19.            
20.     }   
21.   
22.     @Override  
23.     public void doFilter(ServletRequest arg0, ServletResponse arg1,   
24.             FilterChain arg2) throws IOException, ServletException {   
25.         // TODO Auto-generated method stub   
26.         HttpServletRequest request = (HttpServletRequest) arg0;     
27.         HttpServletResponse response = (HttpServletResponse) arg1;    
28.            
29.         String yanzhengm = request.getParameter("j_captcha");   
30.         String sessionyanz = (String)request.getSession(true).getAttribute("yzkeyword");   
31.         if(yanzhengm.equals(sessionyanz)){   
32.             arg2.doFilter(request, response);    
33.         }else{   
34.             response.sendRedirect("/login.do");   
35.         }   
36.     }   
37.   
38.     @Override  
39.     public void init(FilterConfig arg0) throws ServletException {   
40.         // TODO Auto-generated method stub   
41.            
42.     }   
43.   
44.        
45. }  
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
		
	}

	
}
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

Html代码

spring mvc手机验证码后端登录_java

 

spring mvc手机验证码后端登录_spring mvc手机验证码后端登录_02


1. <%@ page contentType="image/jpeg" import="java.awt.*,java.awt.image.*,java.util.*,javax.imageio.*" pageEncoding="UTF-8"%>  
2. <%!   
3. Color getRandColor(int fc,int bc){//随机获得颜色,RGB格式   
4.         Random random = new Random();   
5.         if(fc>255) fc=255;   
6.         if(bc>255) bc=255;   
7.         int r=fc+random.nextInt(bc-fc);   
8.         int g=fc+random.nextInt(bc-fc);   
9.         int b=fc+random.nextInt(bc-fc);   
10.         return new Color(r,g,b);   
11.         }   
12. %>  
13. <%   
14. //清除缓存,每次访问该页面时都从服务器端读取   
15. response.setHeader("Pragma","No-cache");   
16. response.setHeader("Cache-Control","no-cache");   
17. response.setDateHeader("Expires", 0);   
18.   
19. // 定义显示图片的宽度和高度   
20. int width=60, height=20;   
21. BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);   
22.   
23. // 画图画板   
24. Graphics g = image.getGraphics();   
25.   
26. //定义一个随机数   
27. Random random = new Random();   
28.   
29. // 设置画板背景颜色   
30. g.setColor(getRandColor(200,250));   
31. //设置画板的填充范围   
32. g.fillRect(0, 0, width, height);   
33.   
34. //设置字体   
35. g.setFont(new Font("Times New Roman",Font.PLAIN,18));   
36.   
37. // 设置线条颜色并画线,155条   
38. g.setColor(getRandColor(160,200));   
39. for (int i=0;i<155;i++)   
40. {   
41.  int x = random.nextInt(width);   
42.  int y = random.nextInt(height);   
43.         int xl = random.nextInt(12);   
44.         int yl = random.nextInt(12);   
45.  g.drawLine(x,y,x+xl,y+yl);   
46. }   
47.   
48. // 显示数字,4位长度   
49. String sRand="";   
50. for (int i=0;i<4;i++){   
51.     String rand=String.valueOf(random.nextInt(10));   
52.     sRand+=rand;   
53.     // 设置每个数字的颜色   
54.     g.setColor(new Color(20+random.nextInt(110),20+random.nextInt(110),20+random.nextInt(110)));   
55. //在画板上写数字,起始位置   
56.     g.drawString(rand,13*i+6,16);   
57. }   
58.   
59. // 保存进session   
60. session.setAttribute("yzkeyword",sRand);   
61. //System.out.println("yzm:"+sRand);   
62.   
63.   
64. // 显示图片   
65. g.dispose();   
66.   
67. %>  
68.   
69. <%   
70. //转换成一张图片,格式为JPEG   
71. ImageIO.write(image, "JPEG", response.getOutputStream());   
72. out.clear();//清空缓存的内容。   
73.   
74. pageContext.pushBody();   
75. %>
  1.  
<%@ 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代码

spring mvc手机验证码后端登录_java

 

spring mvc手机验证码后端登录_spring mvc手机验证码后端登录_02


    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans:beans xmlns="http://www.springframework.org/schema/security"  
    3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"  
    4.     xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"  
    5.     xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"  
    6.     xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"  
    7.     xmlns:tool="http://www.springframework.org/schema/tool" xmlns:beans="http://www.springframework.org/schema/beans"  
    8.     xsi:schemaLocation="   
    9.             http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd   
    10.             http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd   
    11.             http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd   
    12.             http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd   
    13.             http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd   
    14.             http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd   
    15.             http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd   
    16.             http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.1.xsd   
    17.             http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"   
    18.     default-lazy-init="true">  
    19.   
    20.   
    21.     <http security="none" pattern="/index.do" />  
    22.   
    23.   
    24.     <http auto-config='true' access-decision-manager-ref="accessDecisionManager"  
    25.         access-denied-page="/index.do">  
    26.         <intercept-url pattern="/demo.do*" access="IS_AUTHENTICATED_REMEMBERED" />  
    27.         <intercept-url pattern="/**/*.do*" access="HODLE" />  
    28.         <logout logout-url="/logout.do" invalidate-session="true"  
    29.             logout-success-url="/logout.jsp" />  
    30.         <form-login login-page="/index.do" default-target-url="/frame.do"  
    31.             always-use-default-target="true" authentication-failure-url="/index.do?login_error=1" />  
    32.         <session-management>  
    33.             <concurrency-control max-sessions="1" expired-url="/timeout.jsp"/>  
    34.         </session-management>  
    35.            
    36.         <remember-me key="jbcpPetStore" />    
    37.     </http>  
    38.   
    39.   
    40.   
    41.     <!-- Automatically receives AuthenticationEvent messages -->  
    42.     <beans:bean id="loggerListener"  
    43.         class="org.springframework.security.authentication.event.LoggerListener" />  
    44.   
    45.     <authentication-manager erase-credentials="false">  
    46.         <authentication-provider user-service-ref="userService">  
    47.             <password-encoder hash="md5" />  
    48.         </authentication-provider>  
    49.     </authentication-manager>  
    50.   
    51.     <beans:bean id="userService" class="com.piaoyi.common.security.UserService" />  
    52.   
    53.     <beans:bean id="accessDecisionManager"  
    54.         class="org.springframework.security.access.vote.AffirmativeBased">  
    55.         <beans:property name="decisionVoters">  
    56.             <beans:list>  
    57.                 <beans:bean class="org.springframework.security.access.vote.RoleVoter" />  
    58.                 <beans:bean  
    59.                     class="org.springframework.security.access.vote.AuthenticatedVoter" />  
    60.                 <beans:bean class="com.piaoyi.common.security.DynamicRoleVoter" />  
    61.             </beans:list>  
    62.         </beans:property>  
    63.     </beans:bean>  
    64. </beans:beans>