SpringSecurity3.X--验证码

目录

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一致,如下所示:

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

 效果图如下:

 

 

另外,从网上也看到了类似的解决方案:

springsecurity3和JCaptcha的整合

里面使用到了jcaptcha的jar包,我整合后发现也很好用,附件中给出jar包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值