1.AuthorizationServerConfigurerAdapter:类
这个类实现了AuthorizationServerConfigurer 我们在搭建auth服务的时候需要写一个配置类 继承这个类 并重写这三个方法 (要加上@EnableAuthorizationServer注解才能生效)
接下来 一一介绍里边的组件
Client相关配置
ClientDetailsServiceConfigurer: 用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。
ClientDetailsService:该接口只提供了一个获取方法 loadClientByClientId 用于获取client
配置方式 :(这里内部使用了建造者模式 )
声明个性客户端及其相关属性,且必须声明至少一个自定义的客户端信息系统才会启动。需要注意,如果需要启用password授权模式,需要特别为AuthorizationServerEndpointsConfigurer提供AuthenticationManager。
注意 :自定义 RedisClientDetailsService 继承了ClientDetailsService 实现loadClientByClientId方法 可以自己定义从哪里获取client
ClientDetails: 这是一个接口 提供了丰富的方法 实现类BaseClientDetails 这个不用说了 看BaseClientDetails源码就知道 这是一个具体client实体
该接口提供了非常丰富的方法 可以实现这个接口自行实现 也可以直接调用
------------------------------------------------------------------------------------------------------------------------------------
AuthorizationServerEndpointsConfigurer:用来配置授权(authorization)以及令牌(token)的访问端点和令牌服务(token services)。来看一下这个类里边的属性 所有的都在这里了
public final class AuthorizationServerEndpointsConfigurer {
private AuthorizationServerTokenServices tokenServices;
private ConsumerTokenServices consumerTokenServices;
private AuthorizationCodeServices authorizationCodeServices;
private ResourceServerTokenServices resourceTokenServices;
//用于定义token存储
private TokenStore tokenStore;
private TokenEnhancer tokenEnhancer;
private AccessTokenConverter accessTokenConverter;
private ApprovalStore approvalStore;
private TokenGranter tokenGranter;
private OAuth2RequestFactory requestFactory;
private OAuth2RequestValidator requestValidator;
private UserApprovalHandler userApprovalHandler;
private AuthenticationManager authenticationManager;
private ClientDetailsService clientDetailsService;
private String prefix;
private Map
private Set allowedTokenEndpointRequestMethods = new HashSet();
private FrameworkEndpointHandlerMapping frameworkEndpointHandlerMapping;
private boolean approvalStoreDisabled;
private List interceptors = new ArrayList();
//组件token 的类 可以进行重写自己实现创建token逻辑
private DefaultTokenServices defaultTokenServices;
//处理用户登录逻辑
private UserDetailsService userDetailsService;
private boolean tokenServicesOverride = false;
private boolean userDetailsServiceOverride = false;
private boolean reuseRefreshToken = true;
//用于自定义返回异常
private WebResponseExceptionTranslator exceptionTranslator;
配置方式 :
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.accessTokenConverter(jwtAccessTokenConverter())
//authenticationManager必须得配置 .authenticationManager(authenticationManager).exceptionTranslator(webResponseExceptionTranslator).reuseRefreshTokens(true)
.userDetailsService(integrationUserDetailsService).allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenServices(defaultTokenServices());
}
AuthenticationManager:接口AuthenticationManager用于抽象建模认证管理器,用于处理一个认证请求,也就是Spring Security中的Authentication认证令牌。
AuthenticationManager接口只定义了一个方法:
Authentication authenticate(Authentication authentication) throws AuthenticationException;
该方法接收一个认证令牌对象,也就是认证请求作为参数,如果其中的信息匹配到目标账号,则该方法返回同一个认证令牌对象,不过其中被认证过程填充了更多的账号信息,比如授权和用户详情等。
DisabledException – 账号被禁用时抛出
LockedException – 账号被锁定时抛出
BadCredentialsException – 密码错误时抛出
Spring Security框架提供了AuthenticationManager的缺省实现ProviderManager。ProviderManager管理了多个身份管理源,或者叫做认证提供者AuthenticationProvider,用于认证用户。它自身不实现身份验证,而是逐一使用认证提供者进行认证,直到某一个认证提供者能够成功地验证该用户的身份(或者是已经尝试完了该集合中所有的认证提供者仍然不能认证该用户的身份)。通过ProviderManager,Spring Security能够为单个应用程序提供多种认证机制。
AuthenticationManager会在Spring Security应用配置阶段被构建,比如被某个WebSecurityConfigurerAdapter构建,然后在工作阶段被使用。比如一个基于用户名密码认证机制的Spring Web MVC + Spring Security应用,应用/容器启动过程中,AuthenticationManager构建后会被设置到基于用户名密码进行认证的安全过滤器UsernamePasswordAuthenticationFilter上,缺省情况下,当请求为访问地址/login的POST请求时,UsernamePasswordAuthenticationFilter就会认为这是一个用户认证请求,从而获取请求中的用户名/密码信息,使用AuthenticationManager认证该请求用户的身份。
流程分析:
AuthenticationManager------>ProviderManager------>AuthenticationProvider------->AbstractUserDetailsAuthenticationProvider ------>DaoAuthenticationProvider
最终 在 abstractUserDetailsAuthenticationProvider 里的 authenticate 方法中
最终是走到这 DaoAuthenticationProvider
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication, this.messages.getMessage(“AbstractUserDetailsAuthenticationProvider.onlySupports”, “Only UsernamePasswordAuthenticationToken is supported”));
String username = authentication.getPrincipal() == null ? “NONE_PROVIDED” : authentication.getName();
boolean cacheWasUsed = true;
UserDetails user = this.userCache.getUserFromCache(username);
if (user == null) {
cacheWasUsed = false;
try {
user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);
} catch (UsernameNotFoundException var6) {
this.logger.debug("User '" + username + "' not found");
if (this.hideUserNotFoundExceptions) {
throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
}
throw var6;
}
Assert.notNull(user, "retrieveUser returned null - a violation of the interface contract");
}
try {
this.preAuthenticationChecks.check(user);
//验证密码
this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);
} catch (AuthenticationException var7) {
if (!cacheWasUsed) {
throw var7;
}
cacheWasUsed = false;
user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication);
this.preAuthenticationChecks.check(user);
this.additionalAuthenticationChecks(user, (UsernamePasswordAuthenticationToken)authentication);
}
this.postAuthenticationChecks.check(user);
if (!cacheWasUsed) {
this.userCache.putUserInCache(user);
}
Object principalToReturn = user;
if (this.forcePrincipalAsString) {
principalToReturn = user.getUsername();
}
return this.createSuccessAuthentication(principalToReturn, authentication, user);
}
参考文章:
https://www.jianshu.com/p/32fa221e03b7
DfaultTokenServices:
Springsecurity默认生成Token的方法是DfaultTokenServices的createAccessToken方法:
UserDetailsService:
这 个接口 只有一个方法 loadUserByUserName
可以自己实现这个接口 自定义从哪里取token
DefaultOAuth2AccessToken:
OAuth2AccessToken的实现类 OAuth2AccessToken接口提供了一些方法
public interface OAuth2AccessToken {
String BEARER_TYPE = “Bearer”;
String OAUTH2_TYPE = “OAuth2”;
String ACCESS_TOKEN = “access_token”;
String TOKEN_TYPE = “token_type”;
String EXPIRES_IN = “expires_in”;
String REFRESH_TOKEN = “refresh_token”;
String SCOPE = “scope”;
Map getAdditionalInformation();
Set getScope();
OAuth2RefreshToken getRefreshToken();
String getTokenType();
boolean isExpired();
Date getExpiration();
int getExpiresIn();
String getValue();
}
TokenEnhancer:token生成策略 可以自己往里边加一些东西例子
https://www.xttblog.com/?p=3742 参考网址
@Bean
public TokenEnhancer tokenEnhancer() {
return (accessToken, authentication) -> {
//client授权返回原串
if (“client_credentials”.equals(authentication.getOAuth2Request().getGrantType())) {
return accessToken;
}
final Map
User user = (User) authentication.getUserAuthentication().getPrincipal();
additionalInfo.put(“userId”, user.getId());
additionalInfo.put(“companyId”,user.getCompanyId());
additionalInfo.put(“departmentId”, user.getDepartmentId());
additionalInfo.put(“roleId”, user.getRoleId());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
return accessToken;
};
}
TokenStore:
用于存储token 可以用来自定义token存储方式
@Bean
public TokenStore tokenstore(){
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
tokenStore.setPrefix(“oauth2:”);
return tokenStore;
}
AuthorizationServerSecurityConfigurer
用来配置令牌端点(Token Endpoint)的安全约束.
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
//开启表单验证
security.allowFormAuthenticationForClients().tokenKeyAccess(“isAuthenticated()”).checkTokenAccess(“permitAll()”)
.addTokenEndpointAuthenticationFilter(integrationAuthenticationFilter);
}
JwtAccessTokenConverter是用来生成token的转换器,而token令牌默认是有签名的,且资源服务器需要验证这个签名。此处的加密及验签包括两种方式:
相关文章 :https://www.cnblogs.com/fp2952/p/8973613.html
PasswordEncoder
用于编码密码的服务接口。首选的实现是BCryptPasswordEncoder。
参考网址:
https://docs.spring.io/spring-security/site/docs/4.2.4.RELEASE/apidocs/org/springframework/security/crypto/password/PasswordEncoder.html