晚上短信验证码功能开发
This commit is contained in:
@@ -3,9 +3,10 @@
|
||||
##相关配置参数说明
|
||||
- `ms.security.browser.html` 自定义登录页面的地址
|
||||
- `ms.security.browser.loginType` 身份认证后响应类型`REDIRECT`页面形式响应
|
||||
- `ms.security.browser.rememberMeSeconds` 记住我的时间,单位是秒。默认的时间是3600秒
|
||||
`JSON` json形式的响应
|
||||
- `ms.security.browser.rememberMeSeconds` 记住我的时间,单位是秒,默认的时间是3600秒
|
||||
`JSON`, json形式的响应
|
||||
- 定义自己的根据用户名获取密码的bean,定义自己的bean的名字为`userServiceImpl`即可
|
||||
- `/authentication/require`处理身份认证跳转的接口地址
|
||||
- 需要注入`userServiceImpl`获取用户详细信息的bean
|
||||
- 需要注入数据源`masterDataSource`用于记住我功能的bean
|
||||
- 需要注入数据源`masterDataSource`用于记住我功能的bean,记住我功能需要在登录的时候传入
|
||||
`remember-me`参数,值为`true`
|
||||
+34
-13
@@ -79,28 +79,44 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
validateCodeFilter.setSecurityProperties(securityProperties);
|
||||
validateCodeFilter.afterPropertiesSet();
|
||||
http
|
||||
.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)//添加自定义的验证码处理器,在用户密码校验过滤器之前
|
||||
.formLogin()//使用表单登录
|
||||
.loginPage("/authentication/require")//自定义登录页面
|
||||
.loginProcessingUrl("/user/login")//配置spring security登录接口的访问地址,用于在自定义的登录页面提交请求
|
||||
.successHandler(msAuthenticationSuccessHandler)//定义身份认证成功后处理对象
|
||||
.failureHandler(msAuthenticationFailureHandler)//定义身份认证失败后处理对象
|
||||
//添加自定义的验证码处理器,在用户密码校验过滤器之前
|
||||
.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
//使用表单登录
|
||||
.formLogin()
|
||||
//自定义登录页面
|
||||
.loginPage("/authentication/require")
|
||||
//配置spring security登录接口的访问地址,用于在自定义的登录页面提交请求
|
||||
.loginProcessingUrl("/user/login")
|
||||
//定义身份认证成功后处理对象
|
||||
.successHandler(msAuthenticationSuccessHandler)
|
||||
//定义身份认证失败后处理对象
|
||||
.failureHandler(msAuthenticationFailureHandler)
|
||||
.and()
|
||||
//记住我功能的相关配置
|
||||
.rememberMe()
|
||||
.tokenRepository(persistentTokenRepository())//设置token的存储方式
|
||||
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())//设置过期秒数
|
||||
.userDetailsService(userDetailsService)//设置获取用户信息后登录的方式
|
||||
//设置token的存储方式
|
||||
.tokenRepository(persistentTokenRepository())
|
||||
//设置过期秒数
|
||||
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
|
||||
//设置获取用户信息后登录的方式
|
||||
.userDetailsService(userDetailsService)
|
||||
.and()
|
||||
.authorizeRequests()//下面是权限配置
|
||||
.antMatchers("/user/login", "/code/*", "/authentication/require", securityProperties.getBrowser().getHtml()).permitAll()//当访问这个页面的时候不进行身份认证,对用户自定义的登录页也不进行权限认证
|
||||
.anyRequest()//任何请求
|
||||
.authenticated()//都需要身份认证
|
||||
//当访问这个页面的时候不进行身份认证,对用户自定义的登录页也不进行权限认证
|
||||
.antMatchers("/user/login", "/code/*", "/authentication/require", securityProperties.getBrowser().getHtml()).permitAll()
|
||||
//任何请求
|
||||
.anyRequest()
|
||||
//都需要身份认证
|
||||
.authenticated()
|
||||
.and()
|
||||
.csrf().disable();//暂时关闭掉跨站请求攻击防护
|
||||
//暂时关闭掉跨站请求攻击防护
|
||||
.csrf().disable();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义身份认证红密码的加密解密类的bean
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
@@ -108,6 +124,11 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于记住我功能
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public PersistentTokenRepository persistentTokenRepository() {
|
||||
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
|
||||
|
||||
@@ -9,7 +9,14 @@
|
||||
- `ms.security.code.image.height`图片验证码高度,默认值是`23` 可以在请求中使用`height`参数设置
|
||||
- `ms.security.code.image.length`图片验证码的code长度,默认是`4` 不能在请求中设置
|
||||
- `ms.security.code.image.expireIn` 图片验证码的有效时间`60`秒 不能在请求中设置
|
||||
- `ms.security.code.image.url` 需要进行验证码校验的地址,默认值是`/user/login` 可以是`/user/*`这种格式,多个适用,号分割 不能在请求中设置
|
||||
- 本着增量开发的原则,可以实现`imageCodeUtil`生成验证码的方法,并定义名称为`validateCodeUtil`的bean便可替换原有的验证码的生成逻辑
|
||||
- 短信验证码获取接口url`/code/sms` 短信验证码
|
||||
- `ms.security.code.image.url` 需要进行验证码校验的地址,默认值是`/user/login` 可以是`/user/*`这种格式,多个适用,号分割
|
||||
不能在请求中设置
|
||||
- 本着增量开发的原则,可以实现`imageCodeUtil`生成验证码的方法,并定义名称为`imageCodeUtil`的bean便可替换原有的图片验证码
|
||||
的生成逻辑
|
||||
- 短信验证码获取接口url`/code/sms`
|
||||
- `ms.security.code.sms.length` 短信验证码code的长度,默认值是`6`,不能在请求中设置
|
||||
- `ms.security.code.sms.expireIn` 短信验证码的默认有效时间是`60`秒,不能在请求中设置
|
||||
- `ms.security.code.sms.url`短信验证码进行耀眼的地址,默认值是`/user/login`,可以是`/user/*`这种格式,多个适用,号分割,不
|
||||
能在请求中设置
|
||||
- 同样的,可以实现`validateCode`生成验证码的方法,并定义名称为`smsCodeUtil`的bean便可替换原有的短信验证码的生成逻辑
|
||||
|
||||
|
||||
+3
-32
@@ -29,18 +29,6 @@ import java.util.Map;
|
||||
@RestController
|
||||
public class ValidateCodeController {
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityProperties;
|
||||
|
||||
@Autowired
|
||||
private ValidateCodeUtil imageCodeUtil;
|
||||
|
||||
@Autowired
|
||||
private ValidateCodeUtil smsCodeUtil;
|
||||
|
||||
@Autowired
|
||||
private SendSmsCode sendSmsCode;
|
||||
|
||||
/**
|
||||
* Collect all objects that implement {@link ValidateCodeProcessor} interface
|
||||
* 收集所有实现了{@link ValidateCodeProcessor} 接口的类
|
||||
@@ -48,29 +36,12 @@ public class ValidateCodeController {
|
||||
@Autowired
|
||||
private Map<String,ValidateCodeProcessor> validateCodeProcessors;
|
||||
|
||||
private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
|
||||
private static final String VALIDATE_CODE_PROCESSOR_SUFFIX = "ValidateCodeProcessor";
|
||||
|
||||
@GetMapping("/code/{type}")
|
||||
public void createCode(HttpServletResponse response, HttpServletRequest request,@PathVariable("type") String type) throws IOException {
|
||||
public void createCode(HttpServletResponse response, HttpServletRequest request,@PathVariable("type") String type) throws IOException, ServletRequestBindingException {
|
||||
//create save send ValidateCode
|
||||
validateCodeProcessors.get(type+"ValidateCodeProcessor").create(new ServletWebRequest(request,response));
|
||||
ImageCode imageCode = (ImageCode) imageCodeUtil.createValidateCode(new ServletWebRequest(request));
|
||||
ValidateCode validateCode = new ValidateCode(imageCode.getCode(),imageCode.getExpireTime());
|
||||
//将验证码对象写入session中
|
||||
sessionStrategy.setAttribute(new ServletWebRequest(request), ValidateCodeConst.SESSION_KEY_IMAGE_CODE,validateCode);
|
||||
//将验证码写入到响应之中
|
||||
ImageIO.write(imageCode.getImage(),"JPEG",response.getOutputStream());
|
||||
}
|
||||
|
||||
@GetMapping("/code/sms")
|
||||
public void createSmsCode(HttpServletResponse response, HttpServletRequest request) throws IOException, ServletRequestBindingException {
|
||||
ValidateCode validateCode = smsCodeUtil.createValidateCode(new ServletWebRequest(request));
|
||||
//将验证码对象写入session中
|
||||
sessionStrategy.setAttribute(new ServletWebRequest(request), ValidateCodeConst.SESSION_KEY_IMAGE_CODE,validateCode);
|
||||
//获取phone,请求中必须包含用户的手机号
|
||||
String phone = ServletRequestUtils.getRequiredStringParameter(request, "phone");
|
||||
//发送验证码的逻辑
|
||||
sendSmsCode.sendCode(phone,validateCode.getCode());
|
||||
validateCodeProcessors.get(type+VALIDATE_CODE_PROCESSOR_SUFFIX).create(new ServletWebRequest(request,response));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* 验证码校验异常,继承自AuthenticationException对象
|
||||
* @author lsy
|
||||
*/
|
||||
public class ValidateCodeException extends AuthenticationException {
|
||||
|
||||
|
||||
+3
-1
@@ -38,6 +38,8 @@ public class ValidateCodeFilter extends OncePerRequestFilter implements Initial
|
||||
|
||||
private Set<String> filterUrl = new HashSet<String>();
|
||||
|
||||
private static final String REQUEST_METHOD = "post";
|
||||
|
||||
/**
|
||||
* 初始化filter url
|
||||
* @throws ServletException
|
||||
@@ -71,7 +73,7 @@ public class ValidateCodeFilter extends OncePerRequestFilter implements Initial
|
||||
}
|
||||
}
|
||||
//在登录post请求的时候对验证码进行校验
|
||||
if (filter && StringUtils.endsWithIgnoreCase(httpServletRequest.getMethod(),"post")){
|
||||
if (filter && StringUtils.endsWithIgnoreCase(httpServletRequest.getMethod(),REQUEST_METHOD)){
|
||||
try{
|
||||
//校验验证码是否正确
|
||||
validate(new ServletWebRequest(httpServletRequest));
|
||||
|
||||
+7
-1
@@ -1,9 +1,13 @@
|
||||
package com.micro.fast.security.core.validate.code.processor;
|
||||
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 验证码校验controller中需要执行操作的抽象接口
|
||||
* @author lsy
|
||||
*/
|
||||
public interface ValidateCodeProcessor {
|
||||
|
||||
@@ -15,7 +19,9 @@ public interface ValidateCodeProcessor {
|
||||
/**
|
||||
* 创建验证码,将验证码写入session中,输出验证码
|
||||
* @param servletWebRequest 封装请求和响应
|
||||
* @throws IOException
|
||||
* @throws ServletRequestBindingException
|
||||
*/
|
||||
void create(ServletWebRequest servletWebRequest);
|
||||
void create(ServletWebRequest servletWebRequest) throws ServletRequestBindingException, IOException;
|
||||
|
||||
}
|
||||
|
||||
+12
-5
@@ -7,12 +7,15 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
|
||||
import org.springframework.social.connect.web.SessionStrategy;
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 验证码controller中执行操作的抽象方法
|
||||
* @author lsy
|
||||
*/
|
||||
public abstract class AbstractValidateCodeProcessor <T extends ValidateCode> implements ValidateCodeProcessor {
|
||||
|
||||
@@ -28,8 +31,10 @@ public abstract class AbstractValidateCodeProcessor <T extends ValidateCode> imp
|
||||
@Autowired
|
||||
private Map<String,ValidateCodeUtil> validateCodeUtils;
|
||||
|
||||
private static final String VALIDATE_CODE_UTIL_SUFFIX = "CodeUtil";
|
||||
|
||||
@Override
|
||||
public void create(ServletWebRequest servletWebRequest) {
|
||||
public void create(ServletWebRequest servletWebRequest) throws ServletRequestBindingException, IOException {
|
||||
T generateCode = generateCode(servletWebRequest);
|
||||
save(servletWebRequest,generateCode);
|
||||
send(servletWebRequest,generateCode);
|
||||
@@ -44,7 +49,7 @@ public abstract class AbstractValidateCodeProcessor <T extends ValidateCode> imp
|
||||
public T generateCode(ServletWebRequest servletWebRequest){
|
||||
String processorType = getProcessorType(servletWebRequest);
|
||||
//根据请求的类型获取指定的验证码生成器
|
||||
ValidateCodeUtil validateCodeUtil = validateCodeUtils.get(processorType + "CodeUtil");
|
||||
ValidateCodeUtil validateCodeUtil = validateCodeUtils.get(processorType + VALIDATE_CODE_UTIL_SUFFIX);
|
||||
return (T) validateCodeUtil.createValidateCode(servletWebRequest);
|
||||
}
|
||||
|
||||
@@ -66,10 +71,12 @@ public abstract class AbstractValidateCodeProcessor <T extends ValidateCode> imp
|
||||
|
||||
/**
|
||||
* 发送验证码的逻辑,延迟到子类中去实现
|
||||
* @param servletWebRequest
|
||||
* @param validateCode 验证码对象
|
||||
* @param servletWebRequest 请求
|
||||
* @param validateCode 验证码
|
||||
* @throws ServletRequestBindingException 请求中不包含phone对象时抛出异常
|
||||
* @throws IOException
|
||||
*/
|
||||
public abstract void send(ServletWebRequest servletWebRequest,T validateCode);
|
||||
public abstract void send(ServletWebRequest servletWebRequest,T validateCode) throws ServletRequestBindingException, IOException;
|
||||
|
||||
/**
|
||||
* 根据请求的url获取请求验证码的类型
|
||||
|
||||
+9
-2
@@ -1,16 +1,23 @@
|
||||
package com.micro.fast.security.core.validate.code.processor.impl;
|
||||
|
||||
import com.micro.fast.security.core.validate.code.pojo.ImageCode;
|
||||
import com.micro.fast.security.core.validate.code.pojo.ValidateCode;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 图片验证码逻辑类
|
||||
* @author lsy
|
||||
*/
|
||||
@Component("imageValidateCodeProcessor")
|
||||
public class ImageValidateCodeProcessor extends AbstractValidateCodeProcessor {
|
||||
@Override
|
||||
public void send(ServletWebRequest servletWebRequest, ValidateCode validateCode) {
|
||||
|
||||
public void send(ServletWebRequest servletWebRequest, ValidateCode validateCode) throws IOException {
|
||||
ImageCode imageCode = (ImageCode)validateCode;
|
||||
//将验证码写入到响应之中
|
||||
ImageIO.write(imageCode.getImage(),"JPEG",servletWebRequest.getResponse().getOutputStream());
|
||||
}
|
||||
}
|
||||
|
||||
+17
-2
@@ -1,14 +1,29 @@
|
||||
package com.micro.fast.security.core.validate.code.processor.impl;
|
||||
|
||||
import com.micro.fast.security.core.validate.code.pojo.ValidateCode;
|
||||
import com.micro.fast.security.core.validate.code.service.SendSmsCode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.ServletRequestBindingException;
|
||||
import org.springframework.web.bind.ServletRequestUtils;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* @author lsy
|
||||
*/
|
||||
@Component("smsValidateCodeProcessor")
|
||||
public class SmsValidateCodeProcessor extends AbstractValidateCodeProcessor{
|
||||
|
||||
@Override
|
||||
public void send(ServletWebRequest servletWebRequest, ValidateCode validateCode) {
|
||||
@Autowired
|
||||
private SendSmsCode sendSmsCode;
|
||||
|
||||
private static final String PHONE = "phone";
|
||||
|
||||
@Override
|
||||
public void send(ServletWebRequest servletWebRequest, ValidateCode validateCode) throws ServletRequestBindingException {
|
||||
//获取phone,请求中必须包含用户的手机号
|
||||
String phone = ServletRequestUtils.getRequiredStringParameter(servletWebRequest.getRequest(), PHONE);
|
||||
//发送验证码的逻辑
|
||||
sendSmsCode.sendCode(phone,validateCode.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -1,5 +1,13 @@
|
||||
package com.micro.fast.security.core.validate.code.service;
|
||||
|
||||
/**
|
||||
* @author lsy
|
||||
*/
|
||||
public interface SendSmsCode {
|
||||
/**
|
||||
* 发送短信验证码
|
||||
* @param phone
|
||||
* @param code
|
||||
*/
|
||||
void sendCode(String phone,String code);
|
||||
}
|
||||
|
||||
+1
@@ -12,6 +12,7 @@ import java.util.Random;
|
||||
|
||||
/**
|
||||
* 图片验证码工具类
|
||||
* @author lsy
|
||||
*/
|
||||
public class ImageCodeUtil implements ValidateCodeUtil{
|
||||
|
||||
|
||||
+6
@@ -5,7 +5,13 @@ import org.springframework.web.context.request.ServletWebRequest;
|
||||
|
||||
/**
|
||||
* 验证码生成的接口
|
||||
* @author Administrator
|
||||
*/
|
||||
public interface ValidateCodeUtil {
|
||||
/**
|
||||
* 生成验证码
|
||||
* @param request 封装request和response的对象
|
||||
* @return 验证码对象
|
||||
*/
|
||||
ValidateCode createValidateCode(ServletWebRequest request);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user