第三方登录

This commit is contained in:
阿沐 2024-02-24 12:21:46 +08:00
parent 6c8966622f
commit 3b4af747ba
5 changed files with 210 additions and 0 deletions

View File

@ -0,0 +1,85 @@
package net.maku.framework.security.third;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.Assert;
/**
* 第三方登录 AuthenticationProvider
*
* @author 阿沐 babamu@126.com
* <a href="https://maku.net">MAKU</a>
*/
public class ThirdAuthenticationProvider implements AuthenticationProvider, InitializingBean, MessageSourceAware {
protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
private final GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
private final ThirdUserDetailsService thirdUserDetailsService;
private final ThirdOpenIdService thirdOpenIdService;
public ThirdAuthenticationProvider(ThirdUserDetailsService thirdUserDetailsService, ThirdOpenIdService thirdOpenIdService) {
this.thirdUserDetailsService = thirdUserDetailsService;
this.thirdOpenIdService = thirdOpenIdService;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Assert.isInstanceOf(ThirdAuthenticationToken.class, authentication,
() -> messages.getMessage(
"ThirdAuthenticationProvider.onlySupports",
"Only ThirdAuthenticationProvider is supported"));
ThirdAuthenticationToken authenticationToken = (ThirdAuthenticationToken) authentication;
ThirdLogin login = (ThirdLogin) authenticationToken.getPrincipal();
try {
// 获取用户 openId
String openId = thirdOpenIdService.getOpenId(login);
// 获取用户信息
UserDetails userDetails = thirdUserDetailsService.loadUserByOpenTypeAndOpenId(login.getOpenType(), openId);
if (userDetails == null) {
throw new BadCredentialsException("Bad credentials");
}
return createSuccessAuthentication(authentication, userDetails);
} catch (UsernameNotFoundException ex) {
throw new BadCredentialsException(this.messages
.getMessage("ThirdAuthenticationProvider.badCredentials", "Bad credentials"));
}
}
protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
ThirdAuthenticationToken result = new ThirdAuthenticationToken(user,
authoritiesMapper.mapAuthorities(user.getAuthorities()));
result.setDetails(authentication.getDetails());
return result;
}
@Override
public boolean supports(Class<?> authentication) {
return ThirdAuthenticationToken.class.isAssignableFrom(authentication);
}
@Override
public void afterPropertiesSet() throws Exception {
Assert.notNull(thirdUserDetailsService, "thirdUserDetailsService must not be null");
Assert.notNull(thirdOpenIdService, "thirdOpenIdService must not be null");
}
@Override
public void setMessageSource(MessageSource messageSource) {
this.messages = new MessageSourceAccessor(messageSource);
}
}

View File

@ -0,0 +1,55 @@
package net.maku.framework.security.third;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.util.Assert;
import java.util.Collection;
/**
* 第三方登录 AuthenticationToken
*
* @author 阿沐 babamu@126.com
* <a href="https://maku.net">MAKU</a>
*/
public class ThirdAuthenticationToken extends AbstractAuthenticationToken {
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private final Object principal;
private Object credentials;
public ThirdAuthenticationToken(Object principal) {
super(null);
this.principal = principal;
setAuthenticated(false);
}
public ThirdAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
super.setAuthenticated(true);
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
Assert.isTrue(!isAuthenticated,
"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
super.setAuthenticated(false);
}
@Override
public Object getCredentials() {
return this.credentials;
}
@Override
public Object getPrincipal() {
return this.principal;
}
@Override
public void eraseCredentials() {
super.eraseCredentials();
this.credentials = null;
}
}

View File

@ -0,0 +1,29 @@
package net.maku.framework.security.third;
import lombok.Data;
import java.io.Serializable;
/**
* 第三方登录 表单数据
*
* @author 阿沐 babamu@126.com
* <a href="https://maku.net">MAKU</a>
*/
@Data
public class ThirdLogin implements Serializable {
/**
* 开放平台类型
*/
private String openType;
/**
* 开放平台Code
*/
private String code;
/**
* state
*/
private String state;
}

View File

@ -0,0 +1,18 @@
package net.maku.framework.security.third;
/**
* 第三方登录通过code获取开放平台用户唯一标识
*
* @author 阿沐 babamu@126.com
* <a href="https://maku.net">MAKU</a>
*/
public interface ThirdOpenIdService {
/**
* 通过code获取开放平台用户唯一标识
*
* @param login 第三方登录信息
* @return 开放平台用户唯一标识
*/
String getOpenId(ThirdLogin login);
}

View File

@ -0,0 +1,23 @@
package net.maku.framework.security.third;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
* 第三方登录ThirdUserDetailsService
*
* @author 阿沐 babamu@126.com
* <a href="https://maku.net">MAKU</a>
*/
public interface ThirdUserDetailsService {
/**
* 通过开放平台类型和唯一标识加载用户信息
*
* @param openType 开放平台类型
* @param openId 开放平台唯一标识
* @return 用户信息
* @throws UsernameNotFoundException 不存在异常
*/
UserDetails loadUserByOpenTypeAndOpenId(String openType, String openId) throws UsernameNotFoundException;
}