开发者社区> aielves> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

spring security3教程系列--扩展验证码

简介: 本文章摘编、转载需要注明来源 http://write.blog.csdn.net/postedit/8575482 security的登录参数验证主要是经过UsernamePasswo...
+关注继续查看

本文章摘编、转载需要注明来源 http://write.blog.csdn.net/postedit/8575482

security的登录参数验证主要是经过UsernamePasswordAuthenticationFilter过滤器

所以我们自己写个新的实现类类继承UsernamePasswordAuthenticationFilter,验证码工具我是使用jcaptcha,相信大家对这个也不会感觉陌生吧,至于网上也有很多这样的例子来演示如何扩展了

先来写个实现类继承UsernamePasswordAuthenticationFilter

/**
 * 重载SECURITY3的UsernamePasswordAuthenticationFilter的attemptAuthentication,
 * obtainUsername,obtainPassword方法(完善逻辑) 增加验证码校验模块 添加验证码属性 添加验证码功能开关属性
 * 
 * @author shadow
 * @email 124010356@qq.com
 * @create 2012.04.28
 */
public class UsernamePasswordAuthenticationExtendFilter extends
		UsernamePasswordAuthenticationFilter {

	// 验证码字段
	private String validateCodeParameter = "validateCode";
	// 是否开启验证码功能
	private boolean openValidateCode = false;

	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		// 只接受POST方式传递的数据
		if (!"POST".equals(request.getMethod()))
			throw new MethodErrorException("不支持非POST方式的请求!");

		// 开启验证码功能的情况
		if (isOpenValidateCode())
			checkValidateCode(request);

		// 获取Username和Password
		String username = obtainUsername(request);
		String password = obtainPassword(request);

		// UsernamePasswordAuthenticationToken实现Authentication校验
		UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
				username, password);

		// 允许子类设置详细属性
		setDetails(request, authRequest);

		// 运行UserDetailsService的loadUserByUsername 再次封装Authentication
		return this.getAuthenticationManager().authenticate(authRequest);
	}

	// 匹对验证码的正确性
	public void checkValidateCode(HttpServletRequest request) {

		String jcaptchaCode = obtainValidateCodeParameter(request);
		if (null == jcaptchaCode)
			throw new ValidateCodeException("验证码超时,请重新获取!");

		boolean b = CaptchaServiceSingleton.getInstance()
				.validateResponseForID(request.getSession().getId(),
						jcaptchaCode);
		if (!b)
			throw new ValidateCodeException("验证码不正确,请重新输入!");
	}

	public String obtainValidateCodeParameter(HttpServletRequest request) {
		Object obj = request.getParameter(getValidateCodeParameter());
		return null == obj ? "" : obj.toString().trim();
	}

	@Override
	protected String obtainUsername(HttpServletRequest request) {
		Object obj = request.getParameter(getUsernameParameter());
		return null == obj ? "" : obj.toString().trim();
	}

	@Override
	protected String obtainPassword(HttpServletRequest request) {
		Object obj = request.getParameter(getPasswordParameter());
		return null == obj ? "" : obj.toString().trim();
	}

	public String getValidateCodeParameter() {
		return validateCodeParameter;
	}

	public void setValidateCodeParameter(String validateCodeParameter) {
		this.validateCodeParameter = validateCodeParameter;
	}

	public boolean isOpenValidateCode() {
		return openValidateCode;
	}

	public void setOpenValidateCode(boolean openValidateCode) {
		this.openValidateCode = openValidateCode;
	}

}


很明显我们在获取username跟password之前执行一个checkValidateCode()的方法,这里就是先比较验证码,如果失败就直接抛出ValidateCodeException,这个异常自己定义个,

只要继承AuthenticationException就可以了


校验成功就直接往下执行比较username,password,然后配置xml的时候class的指向就用自己新的filter,过滤链中使用新的filter替换掉UsernamePasswordAuthenticationFilter实现类的位置,下面是我自己的xml配置

过滤链里的serverCustomUsernamePasswordAuthenticationFilter实现换成是我们自己刚写的实现类,至于com.shadow.security.handler.LoginSuccessHandler和

com.shadow.security.handler.LoginFailureHandler这里自己实现一个AuthenticationSuccessHandler接口里面逻辑根据项目需求来设计

<!-- 登录认证过滤器-->
	<bean id="usernamePasswordAuthenticationFilter"
		class="com.shadow.security.service.UsernamePasswordAuthenticationExtendFilter">
		<property name="authenticationManager"
			ref="authenticationManager" />
		<property name="sessionAuthenticationStrategy"
			ref="concurrentSessionControlStrategy" />
		<property name="usernameParameter" value="username" />
		<property name="passwordParameter" value="password" />
		<property name="validateCodeParameter" value="validateCode" />
		<property name="openValidateCode" value="true" />
		<property name="filterProcessesUrl" value="/login" />
		<property name="rememberMeServices" ref="rememberMeServices" />
		<property name="authenticationSuccessHandler">
			<bean
				class="com.shadow.security.handler.LoginSuccessHandler">
				<property name="indexUrl" value="/index.jsp" />
			</bean>
		</property>
		<property name="authenticationFailureHandler">
			<bean
				class="com.shadow.security.handler.LoginFailureHandler" />
		</property>
	</bean>



至于其他的依赖属性注入就自己根据项目来添加吧,这里就不详细说明了





版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Spring Boot引用配置文件
Spring Boot程序默认从application.properties或者application.yaml读取配置,如何将配置信息外置,方便配置呢?
34 0
Spring Boot 应用可视化监控,一目了然!
Spring Boot 应用可视化监控,一目了然!
195 0
Spring Boot中使用Spring Security进行安全控制
Spring Boot中使用Spring Security进行安全控制
153 0
Spring Boot 实现定时任务的 4 种方式
定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
115 0
企业级 SpringBoot 教程 (二)Spring Boot配置文件详解
springboot采纳了建立生产就绪Spring应用程序的观点。 Spring Boot优先于配置的惯例,旨在让您尽快启动和运行。在一般情况下,我们不需要做太多的配置就能够让spring boot正常运行。
1141 0
Spring boot 通用配置文件模板
001 # =================================================================== 002 # COMMON SPRING BOOT PROPERTIES 003 # 004 # This sample file is provided as a guideline.
1612 0
Spring Boot 启动加载数据 CommandLineRunner
实际应用中,我们会有在项目服务启动的时候就去加载一些数据或做一些事情这样的需求。 为了解决这样的问题,Spring Boot 为我们提供了一个方法,通过实现接口 CommandLineRunner 来实现。
966 0
Spring boot 通用配置文件模板
Spring boot 通用配置文件模板   001 # ===================================================================002 # COMMON SPRING BOOT PROPERTIES003 #004 # This sample file is provided as a guideline.
1580 0
+关注
aielves
一直在超越,从未被模仿...
49
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载