赞
踩
package org.springframework.security.web.authentication.www;
public class BasicAuthenticationConverter implements AuthenticationConverter {
// 主要方法
public UsernamePasswordAuthenticationToken convert(HttpServletRequest request) {
String header = request.getHeader("Authorization");
if (header == null) {
return null;
} else {
header = header.trim();
if (!StringUtils.startsWithIgnoreCase(header, "Basic")) {
return null;
} else if (header.equalsIgnoreCase("Basic")) {
throw new BadCredentialsException("Empty basic authentication token");
} else {
byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);
byte[] decoded = this.decode(base64Token);
String token = new String(decoded, this.getCredentialsCharset(request));
int delim = token.indexOf(":");
if (delim == -1) {
throw new BadCredentialsException("Invalid basic authentication token");
} else {
UsernamePasswordAuthenticationToken result = UsernamePasswordAuthenticationToken.unauthenticated(token.substring(0, delim), token.substring(delim + 1));
result.setDetails(this.authenticationDetailsSource.buildDetails(request));
return result;
}
}
}
}
}
// 自定义类,继承JdbcClientDetailsService 或 ClientDetailsService
public class RedisClientDetailsService extends JdbcClientDetailsService {
/**
* 重写 loadClientByClientId 方法,从缓存中获取客户端的配置信息
*/
@Override
public ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {
ClientDetails clientDetails = null;
String value = RedisUtil.hGet(CACHE_CLIENT_KEY, clientId, RedisDBType.PRIMARY);
if (StringUtils.isBlank(value)) {
clientDetails = cacheAndGetClient(clientId);
} else {
clientDetails = JSONObject.parseObject(value, BaseClientDetails.class);
}
return clientDetails;
}
}
package org.springframework.security.oauth2.provider.endpoint;
public class TokenEndpoint extends AbstractEndpoint {
/**
* 登录方法,获取token信息
*/
@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!allowedRequestMethods.contains(HttpMethod.GET)) {
throw new HttpRequestMethodNotSupportedException("GET");
}
return postAccessToken(principal, parameters);
}
@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = getClientId(principal);
ClientDetails authenticatedClient = getClientDetailsService().loadClientByClientId(clientId);
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(parameters, authenticatedClient);
if (clientId != null && !clientId.equals("")) {
// Only validate the client details if a client authenticated during this
// request.
if (!clientId.equals(tokenRequest.getClientId())) {
// double check to make sure that the client ID in the token request is the same as that in the
// authenticated client
throw new InvalidClientException("Given client ID does not match authenticated client");
}
}
if (authenticatedClient != null) {
oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
}
if (!StringUtils.hasText(tokenRequest.getGrantType())) {
throw new InvalidRequestException("Missing grant type");
}
if (tokenRequest.getGrantType().equals("implicit")) {
throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
}
if (isAuthCodeRequest(parameters)) {
// The scope was requested or determined during the authorization step
if (!tokenRequest.getScope().isEmpty()) {
logger.debug("Clearing scope of incoming token request");
tokenRequest.setScope(Collections.<String> emptySet());
}
}
if (isRefreshTokenRequest(parameters)) {
// A refresh token has its own default scopes, so we should ignore any added by the factory here.
tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
}
OAuth2AccessToken token = getTokenGranter().grant(tokenRequest.getGrantType(), tokenRequest);
if (token == null) {
throw new UnsupportedGrantTypeException("Unsupported grant type: " + tokenRequest.getGrantType());
}
return getResponse(token);
}
}
/**
* 重写类,实现 TokenStore 类
*/
public class MyRedisTokenStore implements TokenStore {
@Override
public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) {
String key = authenticationKeyGenerator.extractKey(authentication);
byte[] serializedKey = serializeKey(FebsConstant.AUTH_TO_ACCESS + key);
byte[] bytes = null;
RedisConnection conn = getConnection();
try {
bytes = conn.get(serializedKey);
} finally {
conn.close();
}
OAuth2AccessToken accessToken = deserializeAccessToken(bytes);
if (accessToken != null) {
OAuth2Authentication storedAuthentication = readAuthentication(accessToken.getValue());
if ((storedAuthentication == null || !key.equals(authenticationKeyGenerator.extractKey(storedAuthentication)))) {
// 将token 信息加载到缓存中
storeAccessToken(accessToken, authentication);
}
}
return accessToken;
}
@Override
public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) {
// 根据token 与 authentication信息自定义缓存
// ...
}
/**
* 重写方法,自定义根据token获取 authentication 信息
*/
@Override
public OAuth2Authentication readAuthentication(String token) {
byte[] bytes = null;
RedisConnection conn = getConnection();
try {
bytes = conn.get(serializeKey(FebsConstant.AUTH + token));
} finally {
conn.close();
}
OAuth2Authentication auth = deserializeAuthentication(bytes);
return auth;
}
/**
* 重写方法,删除token信息
*/
@Override
public OAuth2AccessToken removeAccessToken(String tokenValue){
}
}
/**
* 重写类,实现 UserDetailsService 类
*/
public class MyUserDetailServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 自定义:可写mapper查询出用户信息,放入UserDeatail对象中返回
}
}
/**
* 异常翻译 实现 WebResponseExceptionTranslator 类
*/
public class FebsWebResponseExceptionTranslator implements WebResponseExceptionTranslator {
@Override
public ResponseEntity<?> translate(Exception e) {
ResponseEntity.BodyBuilder status = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
FebsResponse response = new FebsResponse();
String message = "认证失败";
log.error(message, e);
if (e instanceof UnsupportedGrantTypeException) {
message = "不支持该认证类型";
return status.body(response.message(message));
}
if (e instanceof InvalidTokenException
&& StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token (expired)")) {
message = "刷新令牌已过期,请重新登录";
return status.body(response.message(message));
}
if (e instanceof InvalidScopeException) {
message = "不是有效的scope值";
return status.body(response.message(message));
}
if (e instanceof RedirectMismatchException) {
message = "redirect_uri值不正确";
return status.body(response.message(message));
}
if (e instanceof BadClientCredentialsException) {
message = "client值不合法";
return status.body(response.message(message));
}
if (e instanceof UnsupportedResponseTypeException) {
String code = StringUtils.substringBetween(e.getMessage(), "[", "]");
message = code + "不是合法的response_type值";
return status.body(response.message(message));
}
if (e instanceof InvalidGrantException) {
if (StringUtils.containsIgnoreCase(e.getMessage(), "Invalid refresh token")) {
message = "refresh token无效";
return status.body(response.message(message));
}
if (StringUtils.containsIgnoreCase(e.getMessage(), "Invalid authorization code")) {
String code = StringUtils.substringAfterLast(e.getMessage(), ": ");
message = "授权码" + code + "不合法";
return status.body(response.message(message));
}
if (StringUtils.containsIgnoreCase(e.getMessage(), "locked")) {
message = "用户已被锁定,请联系管理员";
return status.body(response.message(message));
}
message = "用户名或密码错误";
return status.body(response.message(message));
}
return status.body(response.message(message));
}
}
/**
* 认证服务器配置
*/
public class MyAuthorizationServerConfigure extends AuthorizationServerConfigurerAdapter {
/**
* token 检查策略
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("permitAll()");
}
/**
* 客户端配置
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// 该对象是2
clients.withClientDetails(redisClientDetailsService);
}
/**
* token 携带额外信息
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
endpoints.tokenStore(tokenStore()) // token信息记录方式
.tokenEnhancer(tokenEnhancerChain)
.userDetailsService(userDetailService) // 对象5
.authorizationCodeServices(authenticationCodeService) // 咱不知道用途
.authenticationManager(authenticationManager) // 咱不知道用途
.exceptionTranslator(exceptionTranslator); // 对象6
// 是否开启jwt认证
if (properties.getEnableJwt()) {
endpoints.accessTokenConverter(jwtAccessTokenConverter());
}
}
/**
* 注入TokenStore
*/
@Bean
public TokenStore tokenStore() {
// 是否开启jwt认证
if (properties.getEnableJwt()) {
return new JwtTokenStore(jwtAccessTokenConverter());
} else {
// 使用自定义类 对象4
MyRedisTokenStore redisTokenStore = new MyRedisTokenStore(redisConnectionFactory);
// 解决每次生成的 token都一样的问题
redisTokenStore.setAuthenticationKeyGenerator(oAuth2Authentication -> UUID.randomUUID().toString());
return redisTokenStore;
}
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。