//@EnableWebSecurity
@Component
public class SecurityConfig extends AbstractChannelSecurityConfig {
@Autowired
private SecurityProperties securityProperties;
@Autowired
private AuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private AuthenticationFailureHandler authenticationFailureHandler;
// @Bean
// public PasswordEncoder passwordEncoder(){
// return new BCryptPasswordEncoder();
// }
@Autowired
private ValidateCodeSecurityConfig validateCodeSecurityConfig;
@Autowired
private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;
@Override
protected void configure(HttpSecurity http) throws Exception {
applyPasswordAuthenticationConfig(http);
http
.apply(validateCodeSecurityConfig)
.and()
.apply(smsCodeAuthenticationSecurityConfig)
.and()
.rememberMe()
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
.userDetailsService(userDetailsService)
.and()
.authorizeRequests()
.antMatchers( "/login",
"/myLogin",
"/loginMobile",
"/css/**", "/images/**", "/js/**","/fonts/**",
"/h2/**","/h2-console/**","/code/*"
)
.permitAll()
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable()
.and()
.csrf().disable();
}
// 内存级别用户
// @Override
// @Bean
// public UserDetailsService userDetailsService(){
// InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
// manager.createUser(User.withUsername("user").password(new BCryptPasswordEncoder().encode("lh123")).roles("USER").build());
// manager.createUser(User.withUsername("fly").password(new BCryptPasswordEncoder().encode("lh123")).roles("ADMIN").build());
// return manager;
// }
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
// @Bean
// public AuthenticationProvider authenticationProvider() {
// DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
// authenticationProvider.setUserDetailsService(userDetailsService);
// authenticationProvider.setPasswordEncoder(passwordEncoder);
// return authenticationProvider;
// }
/**
* 认证信息管理
*/
// @Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth.userDetailsService(userDetailsService);
// auth.authenticationProvider(authenticationProvider());
// }
@Autowired
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
tokenRepository.setCreateTableOnStartup(true);
return tokenRepository;
}
}
public class AbstractChannelSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
protected AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;
@Autowired
protected AuthenticationFailureHandler imoocAuthenticationFailureHandler;
protected void applyPasswordAuthenticationConfig(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/myLogin")
.loginProcessingUrl("/login")
.successHandler(imoocAuthenticationSuccessHandler)
.failureHandler(imoocAuthenticationFailureHandler);
}
}
/**
* 将随机验证码过滤器配置到 spring security 过滤器认证最前端
*/
@Component
public class ValidateCodeSecurityConfig extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
private Filter validateCodeFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.addFilterBefore(validateCodeFilter, AbstractPreAuthenticatedProcessingFilter.class);
}
}
/**
* 保存的密码是加密或未加密都可以,兼容老系统
*/
@Component("passwordEncoder")
public class MyPasswordEncoder extends BCryptPasswordEncoder {
private Pattern BCRYPT_PATTERN = Pattern
.compile("\A\$2(a|y|b)?\$(\d\d)\$[./0-9A-Za-z]{53}");
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
// 数据库密码没加密
if (!BCRYPT_PATTERN.matcher(encodedPassword).matches()) {
System.out.println("rawPassword = " + rawPassword);
System.out.println("encodedPassword = " + encodedPassword);
// TODO 如果密码正确更新为加密的密码
return rawPassword.equals(encodedPassword);
}
return super.matches(rawPassword, encodedPassword);
}
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<title>登录</title>
<link rel="stylesheet" th:href="@{/css/element-ui2.13.2/index.css}" type="text/css">
<script th:src="@{/js/vue.min.js}"></script>
<script th:src="@{/js/vue-router.min.js}"></script>
<script th:src="@{/js/element-ui2.13.2/index.js}"></script>
<script th:src="@{/js/axios.min.js}"></script>
<script th:src="@{/js/jquery.min.js}"></script>
</head>
<body>
<div id="login">
<el-form :model="ruleForm" size="medium" ref="ruleFormRef" label-width="100px">
<el-form-item label="username">
<el-input v-model="ruleForm.username"></el-input>
</el-form-item>
<el-form-item label="password">
<!--show-password-->
<el-input v-model="ruleForm.password"></el-input>
</el-form-item>
<el-form-item label="imageCode">
<el-row>
<el-col :span="8">
<el-input v-model="ruleForm.imageCode"></el-input>
</el-col>
<el-col :span="4">
<div @click="getCaptcha">
<img style=" 100px; height: 50px" alt="验证码" title="点击获取验证码"
:src="captchaUri"/>
</div>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="rememberMe">
<el-checkbox label="记住我" v-model="ruleForm.rememberMe"></el-checkbox>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleFormRef')">submit</el-button>
<el-button @click="resetForm('ruleFormRef')">reset</el-button>
</el-form-item>
</el-form>
<h2>短信登录</h2>
<el-form :model="smsForm" size="medium" ref="smsFormRef" label-width="100px">
<el-form-item label="username">
<el-input v-model="smsForm.mobile"></el-input>
</el-form-item>
<el-form-item label="smsCode">
<el-row>
<el-col :span="8">
<el-input v-model="smsForm.smsCode"></el-input>
</el-col>
<el-col :span="4">
<div>
<button @click="sendSmsCaptcha">发送验证码</button>
</div>
</el-col>
</el-row>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitSmsForm('smsFormRef')">submit</el-button>
<el-button @click="resetForm('smsFormRef')">reset</el-button>
</el-form-item>
</el-form>
</div>
<script>
var vue = new Vue({
el: "#login",
data: {
ruleForm: {
username: '',
password: '',
imageCode: '',
rememberMe:false
},
smsForm:{
mobile:'17811111112',
smsCode:''
},
rules: {
username: [
{required: true, message: 'please input username', trigger: 'blur'},
],
imageCode: [
{required: true, message: 'please input imageCode', trigger: 'blur'},
],
mobile:[
{required: true, message: 'please input mobile', trigger: 'blur'},
],
smsCode:[
{required: true, message: 'please input smsCode', trigger: 'blur'},
]
},
captchaUri: '/code/image?width=100&height=50'
},
methods: {
getCaptcha: function () {
//点击获取验证码
this.captchaUri = this.captchaUri + Math.random()
},
sendSmsCaptcha:function(){
if (this.smsForm.mobile==''){
this.$message.warn("请输入手机号");
return
}
$.ajax({
type: 'GET',
data: {
'mobile': this.smsForm.mobile
},
url: '/code/sms',
dataType: 'json'
});
},
submitSmsForm:function(formName){
var that = this;
$.ajax({
type: 'POST',
data: {
'mobile': this.smsForm.mobile,
'smsCode': this.smsForm.smsCode,
},
url: '/loginMobile',
dataType: 'json',
success: function (res) {
if (res.error_code == '0') {
window.location.href = "http://localhost:9090/home"
} else {
this.$message.error(res.message || "登录失败");
}
},
error: function (res) {
that.$message.error(res.responseJSON.message || "登录失败");
}
});
},
submitForm: function (formName) {
var that = this;
$.ajax({
type: 'POST',
data: {
'username': this.ruleForm.username,
'password': this.ruleForm.password,
'imageCode': this.ruleForm.imageCode,
'remember-me': this.ruleForm.rememberMe
},
url: '/login',
dataType: 'json',
success: function (res) {
if (res.error_code == '0') {
window.location.href = "http://localhost:9090/home"
} else {
this.$message.error(res.message || "用户名或密码错误");
}
},
error: function (res) {
that.$message.error(res.responseJSON.message || "用户名或密码错误");
}
});
// axios.post('/login',{
// username:this.username,
// password:this.password
// }).then(function (res) {
// if (res.error_code=='0'){
// window.location.href="http://localhost:9090/home"
// }
// }).catch(function (err) {
// console.log(err)
// });
},
resetForm: function (formName) {
this.$refs[formName].resetFields();
}
}
})
</script>
</body>
</html>