`
hanqunfeng
  • 浏览: 1526812 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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

  • 大小: 8.5 KB
分享到:
评论
1 楼 愛吃小雪生 2014-05-21  
谷歌浏览器filter好像通不过啊,一直取不到session里面的验证码

相关推荐

    基于Spring Boot 2.x的前后端分离架构X-Boot 后台.zip

    .zip,基于Spring Boot 2.x的前后端分离开发平台X-Boot 前端:Vue iView Admin 后端:Spring Boot 2.x/Spring Security/JWT/Spring Data JPA Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/...

    基于Spring Boot 2.x的一站式前后端分离快速开发平台

    XBoot 微信小程序+Uniapp 前端:Vue+iView Admin 后端:Spring Boot 2.x/Spring Security/JWT/JPA+Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/SnowFlake雪花算法ID生成 动态权限管理 数据...

    x-boot前后端分离开发平台

    基于Spring Boot 2.x的前后端分离开发平台X-Boot 前端:Vue+iView Admin 后端:Spring Boot 2.x/Spring Security/JWT/Spring Data JPA+Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/...

    security-demo:Springboot,SpringSecutity常见演示集

    整理了SpringSecurity常见示例 模块划分,帮你快速掌握Spring Security 1.核心依赖 依赖 版本 Sprint Boot 2.1.6发布 春云 格林威治SR2 Spring安全 2.1.6发布 Spring安全OAuth2 2.1.3发布 胡图尔 4.0.5 2.模块整理...

    java版商城源码下载-learning-project:该项目收集一些优秀的开源项目

    Security/JWT/Spring Data JPA+Mybatis-Plus/Redis/Elasticsearch/Activiti 分布式限流/同步锁/验证码/SnowFlake雪花算法ID生成 动态权限管理 数据权限 工作流 代码生成 日志 定时任务 第三方社交账号、短信登录 单...

    xboot-front:基于Vue + iView Admin开发的XBoot前初始化分离开放平台前端权限可控制至按钮显示动态路由权限菜单多语言简洁美观的前瞻分离

    涉及技术:Spring Boot 2.x / Spring Security / JWT / Spring Data JPA + Mybatis-Plus / Redis / Elasticsearch分布式限流/同步锁/验证码/ SnowFlake雪花算法ID生成动态权限管理定时任务第三方账号,短信登录 ...

    Web安全培训ppt(适合初学者)

    开发工具:安全框架Spring security、 shiro、Spring boot 3、安全工具和设备(2天) DDos防护、WAF、主机入侵防护等等 4、网站安全工具(1天) 阿里云、云狗、云盾 网站在线检测:http://webscan.360.cn/ ...

    JAVA上百实例源码以及开源项目源代码

     Java绘制图片火焰效果,源代码相关注释:前景和背景Image对象、Applet和绘制火焰的效果的Image对象、Applet和绘制火焰的效果的Graphics对象、火焰效果的线程、Applet的高度,图片到图片装载器、绘制火焰效果的X坐标...

    JAVA上百实例源码以及开源项目

     Java绘制图片火焰效果,源代码相关注释:前景和背景Image对象、Applet和绘制火焰的效果的Image对象、Applet和绘制火焰的效果的Graphics对象、火焰效果的线程、Applet的高度,图片到图片装载器、绘制火焰效果的X坐标...

    mallcloud商城-其他

    3、深度定制Spring Security真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案 4、提供应用管理,方便第三方系统接入 5、引入组件化的思想实现高内聚低耦合,项目代码简洁注释丰富上手容易 6、注重...

    mallcloud商城 v1.0

    3、深度定制Spring Security真正实现了基于RBAC、jwt和oauth2的无状态统一权限认证的解决方案 4、提供应用管理,方便第三方系统接入 5、引入组件化的思想实现高内聚低耦合,项目代码简洁注释丰富上手容易 6、注重...

    asp.net知识库

    ASP.NET 2.0 Security FAQs Asp.net 2.0功能体验,细节之Web控件(一) 隐藏控件 Asp.net 2.0功能体验,总体设计思想 Asp.net 2.0 WebPart使用经验点滴 革新:.NET 2.0的自定义配置文件体系初探 关于如何在ASP.NET ...

Global site tag (gtag.js) - Google Analytics