feat:oauth2认证自定义异常

This commit is contained in:
haoxr 2020-09-21 18:02:47 +08:00
parent 24673ebff8
commit 3393516251
7 changed files with 145 additions and 20 deletions

View File

@ -10,12 +10,9 @@
<packaging>pom</packaging>
<modules>
<module>youlai-admin</module>
<module>youlai-common</module>
<module>youlai-auth</module>
<module>youlai-admin-api</module>
<module>youlai-admin</module>
<module>youlai-admin-api</module>
<module>youlai-auth</module>
</modules>

View File

@ -15,16 +15,4 @@ import java.util.TreeMap;
@Component
@AllArgsConstructor
public class ResourceRoleRulesHolder {
private RedisTemplate redisTemplate;
@PostConstruct
public void initResourceRolesMap() {
Map<String, List<String>> resourceRoleMap = new TreeMap<>();
List<String> roleNames = new ArrayList<>();
roleNames.add(AuthConstants.AUTHORITY_PREFIX + "1");
resourceRoleMap.put("/youlai-admin/**", roleNames);
redisTemplate.delete(AuthConstants.RESOURCE_ROLES_MAP_KEY);
redisTemplate.opsForHash().putAll(AuthConstants.RESOURCE_ROLES_MAP_KEY, resourceRoleMap);
}
}
}

View File

@ -0,0 +1,33 @@
package com.youlai.auth.component;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.youlai.auth.exception.CustomOAuth2Exception;
import com.youlai.common.core.result.ResultCodeEnum;
import lombok.SneakyThrows;
/**
* 异常信息格式化
*
* @author haoxr
* @date 2020/09/21
*/
public class OAuth2ExceptionSerializer extends StdSerializer<CustomOAuth2Exception> {
public OAuth2ExceptionSerializer() {
super(CustomOAuth2Exception.class);
}
@Override
@SneakyThrows
public void serialize(CustomOAuth2Exception e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {
jsonGenerator.writeStartObject();
jsonGenerator.writeObjectField("code",e.getOAuth2ErrorCode());
jsonGenerator.writeStringField("msg", e.getMessage());
jsonGenerator.writeStringField("data", e.getOAuth2ErrorCode());
jsonGenerator.writeEndObject();
}
}

View File

@ -0,0 +1,79 @@
package com.youlai.auth.component;
import com.youlai.auth.exception.CustomOAuth2Exception;
import com.youlai.common.core.result.ResultCodeEnum;
import lombok.SneakyThrows;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.DefaultThrowableAnalyzer;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.ClientAuthenticationException;
import org.springframework.security.oauth2.common.exceptions.InsufficientScopeException;
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.web.util.ThrowableAnalyzer;
import org.springframework.stereotype.Component;
/**
* 认证接口异常转换器
*
* @author haoxr
* @date 2020/09/21
*/
@Component
public class OAuth2WebResponseExceptionTranslator implements WebResponseExceptionTranslator {
private ThrowableAnalyzer throwableAnalyzer = new DefaultThrowableAnalyzer();
@Override
@SneakyThrows
public ResponseEntity<OAuth2Exception> translate(Exception e) {
Throwable[] causeChain = throwableAnalyzer.determineCauseChain(e);
Exception exception = (InvalidGrantException) throwableAnalyzer.getFirstThrowableOfType(InvalidGrantException.class,
causeChain);
if (exception != null) {
return handleOAuth2Exception(new InvalidException());
}
return null;
}
private ResponseEntity<OAuth2Exception> handleOAuth2Exception(OAuth2Exception e) {
int status = e.getHttpErrorCode();
HttpHeaders headers = new HttpHeaders();
headers.set(HttpHeaders.CACHE_CONTROL, "no-store");
headers.set(HttpHeaders.PRAGMA, "no-cache");
if (status == HttpStatus.UNAUTHORIZED.value() || (e instanceof InsufficientScopeException)) {
headers.set(HttpHeaders.WWW_AUTHENTICATE,
String.format("%s %s", OAuth2AccessToken.BEARER_TYPE, e.getSummary()));
}
// 客户端异常直接返回客户端,不然无法解析
if (e instanceof ClientAuthenticationException) {
return new ResponseEntity<>(e, headers, HttpStatus.valueOf(status));
}
return new ResponseEntity<>(new CustomOAuth2Exception(e.getMessage(), e.getOAuth2ErrorCode()), headers,
HttpStatus.valueOf(status));
}
private static class InvalidException extends OAuth2Exception {
public InvalidException() {
super(ResultCodeEnum.USER_PASSWORD_ERROR.getMsg());
}
@Override
public String getOAuth2ErrorCode() {
return ResultCodeEnum.USER_PASSWORD_ERROR.getCode();
}
@Override
public int getHttpErrorCode() {
return HttpStatus.BAD_REQUEST.value();
}
}
}

View File

@ -1,5 +1,6 @@
package com.youlai.auth.config;
import com.youlai.auth.component.OAuth2WebResponseExceptionTranslator;
import com.youlai.auth.domain.User;
import com.youlai.auth.service.JdbcClientDetailsServiceImpl;
import com.youlai.auth.service.UserDetailsServiceImpl;
@ -39,6 +40,7 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
private DataSource dataSource;
private AuthenticationManager authenticationManager;
private UserDetailsServiceImpl userDetailsService;
private OAuth2WebResponseExceptionTranslator oAuth2WebResponseExceptionTranslator;
/**
* 配置客户端详情
@ -68,9 +70,11 @@ public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdap
.tokenEnhancer(tokenEnhancerChain)
.userDetailsService(userDetailsService)
// refresh token有两种使用方式重复使用(true)非重复使用(false)默认为true
// 1重复使用access token过期刷新时 refresh token过期时间未改变仍以初次生成的时间为准
// 2非重复使用access token过期刷新时 refresh token过期时间延续在refresh token有效期内刷新便永不失效达到无需再次登录的目的
.reuseRefreshTokens(false);
// 1 重复使用access token过期刷新时 refresh token过期时间未改变仍以初次生成的时间为准
// 2 非重复使用access token过期刷新时 refresh token过期时间延续在refresh token有效期内刷新便永不失效达到无需再次登录的目的
.reuseRefreshTokens(false)
// .exceptionTranslator(oAuth2WebResponseExceptionTranslator)
;
}
/**

View File

@ -0,0 +1,24 @@
package com.youlai.auth.exception;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.youlai.auth.component.OAuth2ExceptionSerializer;
import lombok.Getter;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
/**
* 自定义认证异常
*
* @author haoxr
* @date 2020/09/21
*/
@JsonSerialize(using = OAuth2ExceptionSerializer.class)
public class CustomOAuth2Exception extends OAuth2Exception {
@Getter
private String oAuth2ErrorCode;
public CustomOAuth2Exception(String msg, String oAuth2ErrorCode) {
super(msg);
this.oAuth2ErrorCode = oAuth2ErrorCode;
}
}

View File

@ -33,7 +33,7 @@ public class UserDetailsServiceImpl implements UserDetailsService {
String clientId = request.getParameter("client_id");
UserDTO userDTO = adminUserService.loadUserByUsername(username);
if (userDTO == null) {
throw new UsernameNotFoundException("用户名或者密码错误");
throw new UsernameNotFoundException("用户不存在");
}
userDTO.setClientId(clientId);
User user = new User(userDTO);