1.短信登录配置及重构
- 短信登录一部分配置主要是配置以下3个组件:
主要是配置:SmsCodeAuthenticationFilter和SmsCodeAuthenticationProvider;
SmsCodeAuthenticationToken是封装数据,是不用配置的。
- 另一部分配置是短信过滤器配置:SmsCodeFilter
1.1 过滤器链上组件配置
我们在spring-security-core项目创建一个SmsCodeAuthenticationSecurityConfig;我们没有向之前WebSecurityConfig一样配置在spring-security-web里面;原因是因为:短信校验模块这段配置后面我们既要在web浏览器端使用还要在App端使用。所以我们单独提出一个类。
@Configuration
public class SmsCodeAuthenticationSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler myAuthenticationFailureHandler;
@Autowired
private UserDetailsService myUserDetailsService;
@Override
public void configure(HttpSecurity http) throws Exception {
/* super.configure(builder);*/
//1.按照过滤器链路:配置SmsCodeAutnenticationFilter-->配置让其加入到AuthenticationManager中 配置其成功处理 失败处理的Handler
SmsCodeAuthenticationFilter smsCodeAuthenticationFilter = new SmsCodeAuthenticationFilter();
smsCodeAuthenticationFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
smsCodeAuthenticationFilter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
smsCodeAuthenticationFilter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
//2.配置SmsCodeAuthenticationProvider-->添加UserDetailService
SmsCodeAuthenticationProvider smsCodeAuthenticationProvider = new SmsCodeAuthenticationProvider();
smsCodeAuthenticationProvider.setUserDetailsService(myUserDetailsService);
//3.http配置:配置SmsCodeAutnenticationFilter执行位置--->在UsernamePasswordAuthenticationFilter之后
http.authenticationProvider(smsCodeAuthenticationProvider)
.addFilterAfter(smsCodeAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
}
}
1.2 验证码过滤器配置
在Spring-security-web里面配置:SmsCodeFilter在UsernamePasswordFilter前面
1.3 SmsCodeAuthenticationSecurityConfig配置到WebSecurityConfig
我们把spring-security-core里面的SmsCodeAuthenticationSecurityConfig也配置导入到spring-security-web下面的:WebSecurityConfig配置中:
1.4 测试查看效果
http://127.0.0.1:8088/login.html
- 点击短信登录的登录后返回:
- 点击发送验证码
向手机:13012345678 发送短信验证码:711828
- 我们输入短信验证码,然后登录
得出结果:
2.短信登录重构
现在为止,两种登录方式都已经开发完了。
- 他们都可以在一个系统里面同时生效。
- 底层都是Spring Security,采用的是同一种机制和流程,但是认证的逻辑是不同的。
目前代码重构主要是做两方面内容:
消除重复: 短信验证码和图形验证码里面重复的代码,因为我们是做的拷贝粘铁,然后做了一些简单修改。实现的短信验证码校验功能。 重复的代码是代码坏味道 里面最常见和最严重的。他使得你的代码难以维护,虽然开发时候挺快的,一旦业务逻辑变化,修改代码时候,你可能需要把复制粘贴地方都要修改。重复一个功能模块、小到配置项:比如:在WebSecurityConfig里面:
WebSecurityController里面:
都有相同的代码:/authentication/require
以上修改的时候,你同样需要改变一下,改了一个地方,另一个地方忘记改了,也会出问题。
- 配置抽象:就像我们把短信验证码授权安全配置一样:SmsCodeAuthenticationSecurityConfig 单独抽象到一个类里面。所以这里我们把验证码统一都抽象出来,短信验证码、图形验证码。短信配置的话 也放到一个配置里面去。
- 不管在app端,还是浏览器端应用的一些配置我们都抽取到spring-security-core里面
- 上面基本配置都封装成各个类的话,这样的话在WebSecurityConfig里面只剩下其特有的配置代码;比如:remeberMe就是其特有代码。remeberMe实现是基于往浏览器里面写cookie实现。
- App里面我们会单独写一个AppSecurityConfig配置代码
- 这样的话AppSecurityConfig、WebSecurityConfig可以使用如下引用方法去引用:
AppSecurityConfig、WebSecurityConfig需要支持认证登录的话都得配置。
2.1 验证码校验过滤器合并成一个
验证码校验过滤器合并成一个ValidateCodeFilter;其启动时候会根据系统的配置:
读取到一个map里面去:
/**
* 存放所有需要校验验证码的url
*/
private Map<String, ValidateCodeType> urlMap = new HashMap<>();
里面存放着什么样的验证码使用什么样的处理器。
根据依赖查找查找到对应的校验码处理器:
2.2 密码相关配置抽象
定义一个抽象类:AbstractChannelSecurityConfig 把密码相关配置放在里面。
/*
* @author yexinming
* @date 2020/2/27
*/
public class AbstractChannelSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
protected AuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
protected AuthenticationFailureHandler myAuthenticationFailureHandler;
protected void applyPasswordAuthenticationConfig(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
.loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)
.successHandler(myAuthenticationSuccessHandler)
.failureHandler(myAuthenticationFailureHandler);
}
}
2.3 所有模块配置抽象出来
2.4 字符串抽象
将常用配置项配置到SecurityContants中:
public interface SecurityConstants {
/**
* 默认的处理验证码的url前缀
*/
public static final String DEFAULT_VALIDATE_CODE_URL_PREFIX = "/code";
/**
* 当请求需要身份认证时,默认跳转的url
*
* @see SecurityController
*/
public static final String DEFAULT_UNAUTHENTICATION_URL = "/authentication/require";
/**
* 默认的用户名密码登录请求处理url
*/
public static final String DEFAULT_LOGIN_PROCESSING_URL_FORM = "/authentication/form";
/**
* 默认的手机验证码登录请求处理url
*/
public static final String DEFAULT_LOGIN_PROCESSING_URL_MOBILE = "/authentication/mobile";
/**
* 默认登录页面
*
* @see SecurityController
*/
public static final String DEFAULT_LOGIN_PAGE_URL = "/login.html";
/**
* 验证图片验证码时,http请求中默认的携带图片验证码信息的参数的名称
*/
public static final String DEFAULT_PARAMETER_NAME_CODE_IMAGE = "imageCode";
/**
* 验证短信验证码时,http请求中默认的携带短信验证码信息的参数的名称
*/
public static final String DEFAULT_PARAMETER_NAME_CODE_SMS = "smsCode";
/**
* 发送短信验证码 或 验证短信验证码时,传递手机号的参数的名称
*/
public static final String DEFAULT_PARAMETER_NAME_MOBILE = "mobile";
/**
* session失效默认的跳转地址
*/
public static final String DEFAULT_SESSION_INVALID_URL = "/session/invalid";
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。