# SpringSecurity免密登陆
SpringSecurity免密登陆实现
自定义认证逻辑需要实现和继承三个类分别是
SecurityConfigurerAdapter 构造器 用于配置userDetailsService的实现类
AuthenticationProvider 认证类 定义认证逻辑
AbstractAuthenticationToken 自定义Token 可以自定义Token中的参数
# AbstractAuthenticationToken
继承AbstractAuthenticationToken的类
import java.util.Collection;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
/**
* 邮件登录 AuthenticationToken,模仿 UsernamePasswordAuthenticationToken 实现
*/
public class MailCodeAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
/**
* 在 UsernamePasswordAuthenticationToken 中该字段代表登录的用户名,默认的还有密码,这里只要用户名
*/
private final Object principal;
/**
* 构建一个没有鉴权的 SmsCodeAuthenticationToken
*/
public MailCodeAuthenticationToken(Object principal) {
super(null);
this.principal = principal;
setAuthenticated(false);
}
/**
* 构建拥有鉴权的 SmsCodeAuthenticationToken
*/
public MailCodeAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
// must use super, as we override
super.setAuthenticated(true);
}
@Override
public Object getCredentials() {
return null;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
if (isAuthenticated) {
throw new IllegalArgumentException(
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
}
super.setAuthenticated(false);
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# AuthenticationProvider
实现AuthenticationProvider
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
public class MailCodeAuthenticationProvider implements AuthenticationProvider {
private UserDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
MailCodeAuthenticationToken authenticationToken = (MailCodeAuthenticationToken) authentication;
String mobile = (String) authenticationToken.getPrincipal();
// checkMailCode(mobile);
UserDetails userDetails = userDetailsService.loadUserByUsername(mobile);
// 此时鉴权成功后,应当重新 new 一个拥有鉴权的 authenticationResult 返回
MailCodeAuthenticationToken authenticationResult = new MailCodeAuthenticationToken(userDetails,
userDetails.getAuthorities());
authenticationResult.setDetails(authenticationToken.getDetails());
return authenticationResult;
}
@Override
public boolean supports(Class<?> authentication) {
// 判断 authentication 是不是 MailCodeAuthenticationToken 的子类或子接口
return MailCodeAuthenticationToken.class.isAssignableFrom(authentication);
}
public UserDetailsService getUserDetailsService() {
return userDetailsService;
}
public void setUserDetailsService(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# SecurityConfigurerAdapter
继承SecurityConfigurerAdapter
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.stereotype.Component;
import com.workflow.framework.web.service.UserDetailsServiceImpl;
@Component
public class MailCodeAuthenticationSecurityConfig
extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Override
public void configure(HttpSecurity http) throws Exception {
/*
* MailCodeAuthenticationFilter MailCodeAuthenticationFilter = new
* MailCodeAuthenticationFilter();
* MailCodeAuthenticationFilter.setAuthenticationManager(http.getSharedObject(
* AuthenticationManager.class));
* MailCodeAuthenticationFilter.setAuthenticationSuccessHandler(
* customAuthenticationSuccessHandler);
* MailCodeAuthenticationFilter.setAuthenticationFailureHandler(
* customAuthenticationFailureHandler);
*/
MailCodeAuthenticationProvider mailCodeAuthenticationProvider = new MailCodeAuthenticationProvider();
mailCodeAuthenticationProvider.setUserDetailsService(userDetailsService);
http.authenticationProvider(mailCodeAuthenticationProvider);
/*
* http.authenticationProvider(smsCodeAuthenticationProvider)
* .addFilterAfter(smsCodeAuthenticationFilter,
* UsernamePasswordAuthenticationFilter.class);
*/
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 修改SecurityConfig
/**
* 自定义认证逻辑
*/
@Autowired
private MailCodeAuthenticationSecurityConfig mailCodeAuthenticationSecurityConfig;
//configure方法
httpSecurity.apply(mailCodeAuthenticationSecurityConfig).and()
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10