一:功能说明
- 实现了自定义登录验证(AuthenticationProvider)
二:具体代码
1.自定义AuthenticationProvider
/**
* @author LEI
* Created by LEI on 2019/5/30.
*/
@Component
public class MyAuthenticationProvider implements AuthenticationProvider {
@Autowired
SecurityUserServiceImpl userService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
MyUserAuthentication myUserAuthentication = (MyUserAuthentication) authentication;
String name = myUserAuthentication.getName();
String password = myUserAuthentication.getCredentials().toString();
String verifyCode = myUserAuthentication.getVerifyCode();
// 验证码是否正确 测试写死123456
if(verifyCode.equals("123456")){
UserDetails userDetails = userService.loadUserByUsername(name);
//验证用户名
if(userDetails == null||userDetails.getUsername() == null){
throw new UsernameNotFoundException("用户名未找到");
}
//验证用户密码
if(userDetails.getPassword().equals(DigestUtils.md5DigestAsHex(password.getBytes()))){
//如果账户被禁用
if(!userDetails.isEnabled()){
throw new DisabledException("用户被禁用");
}
return new UsernamePasswordAuthenticationToken(name, null, userDetails.getAuthorities());
}
//用户密码错误
throw new BadCredentialsException("用户凭证错误");
}else {
throw new VerifyCodeException("验证码错误");
}
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(
MyUserAuthentication.class);
}
}
2.将Provider放到认证管理器中
说明: ProviderManager会
依次调用各个AuthenticationProvider
进行认证,认证成功后返回一个封装了用户权限等信息的Authentication
对象。
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
/*
放弃以前的认证方式
auth.userDetailsService(userService).passwordEncoder(new MyPasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
}
*//**
* @param charSequence 明文
* @param s 密文
* @return
*//*
@Override
public boolean matches(CharSequence charSequence, String s) {
System.err.println("matches--------->:" + charSequence);
//如果s密码输入为空
return !StringUtils.isEmpty(s) && s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
}
@Override
public void getUsername(String username) {
System.err.println("username--------->:" + username);
}
});*/
}
}
2020-10-14 添加
如果你需要自定义传参,比方说除了账户密码,还需要验证码,那么你需要这么做
3.UsernamePasswordAuthenticationFilter
package com.core.security.filter;
import com.core.security.bean.AuthenticationBean;
import com.core.security.bean.MyUserAuthentication;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
/**
* @author lei
*/
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
UsernamePasswordAuthenticationToken authRequest;
//System.out.println(request.getRequestURL());
//System.out.println(request.getContentType());
boolean next1 = (request.getContentType()!= null && request.getContentType().toLowerCase().equals(MediaType.APPLICATION_JSON_UTF8_VALUE.toLowerCase()));
boolean next2 = (request.getContentType()!= null &&request.getContentType().toLowerCase().equals(MediaType.APPLICATION_JSON_VALUE.toLowerCase()));
if(next1||next2){
//使用jackson对对象进行反序列化
ObjectMapper mapper = new ObjectMapper();
try (InputStream is = request.getInputStream()){
AuthenticationBean authenticationBean = mapper.readValue(is,AuthenticationBean.class);
// 添加用户认证信息 验证码
// authRequest = new MyUserAuthentication(authenticationBean.getUsername(), authenticationBean.getPassword(),authenticationBean.getVerifyCode(),authenticationBean.getVerifyId());
// 普通只传账户密码
authRequest = new UsernamePasswordAuthenticationToken(authenticationBean.getUsername(), authenticationBean.getPassword());
}catch (IOException e) {
authRequest = new UsernamePasswordAuthenticationToken("", "");
}
setDetails(request, authRequest);
}
//将其传输到 UsernamePasswordAuthenticationFilter
else {
return super.attemptAuthentication(request, response);
}
return this.getAuthenticationManager().authenticate(authRequest);
}
}
4. MyUserAuthentication
package com.core.security.bean;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
/**
* @author LEI
* Created by LEI on 2019/5/30.
*/
public class MyUserAuthentication extends UsernamePasswordAuthenticationToken {
private String verifyCode;
private String verifyId;
/**
* @param principal 用户名
* @param credentials 密码
*/
public MyUserAuthentication(Object principal, Object credentials) {
super(principal, credentials);
}
public MyUserAuthentication(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
super(principal, credentials, authorities);
}
public MyUserAuthentication(Object principal, Object credentials, String verifyCode, String verifyId){
super(principal,credentials);
this.verifyCode = verifyCode;
this.verifyId = verifyId;
}
public String getVerifyCode() {
return verifyCode;
}
public String getVerifyId() {
return verifyId;
}
}