1.拷贝 DaoAuthenticationProvider代码,自定义 MyAuthenticationProvider 继承 AbstractUserDetailsAuthenticationProvider
在retrieveUser方法添加user_type
protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
this.prepareTimingAttackProtection();
Map<String,String> map = (Map<String, String>) authentication.getDetails();
try {
String user_type = map.get("user_type");
UserDetails loadedUser = this.getUserDetailsService().loadUserByLoginName(username,user_type);
if (loadedUser == null) {
throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");
} else {
return loadedUser;
}
} catch (UsernameNotFoundException var4) {
this.mitigateAgainstTimingAttack(authentication);
throw var4;
} catch (InternalAuthenticationServiceException var5) {
throw var5;
} catch (Exception var6) {
throw new InternalAuthenticationServiceException(var6.getMessage(), var6);
}
}
2.在WebSecurityConfigurer 内使用自定义AuthenticationManagerBuilder配置
@Bean(name="myAuthenticationProvider")
public AuthenticationProvider myAuthenticationProvider() {
MyAuthenticationProvider daoAuthenticationProvider = new MyAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(baseUserDetailsService);
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
@Override
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(myAuthenticationProvider());
}
3.在UserDetailsService基础service 添加自定义方法 loadUserByLoginName(String username,String user_type)
在impl内根据user_type查询用户信息
@Override
public UserDetails loadUserByLoginName(String loginName, String userType) throws UsernameNotFoundException {
JSONResult<UserInfo> result=null;
if(SecurityConstants.USER_TYPE_ADMIN.equals(userType)){
result = userServiceApi.info(loginName, SecurityConstants.FROM_IN);
}else if(SecurityConstants.USER_TYPE_UAC.equals(userType)){
result = subscriberServiceApi.info(loginName,SecurityConstants.FROM_IN);
}
return getUserDetails(result);
}
二:在刷新token时为防止调用原来的loadUserByUsername 需要配置自定义tokenServices
1.在AuthorizationServerConfig 内添加
private CustomTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
CustomTokenServices tokenServices = new CustomTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setReuseRefreshToken(true);
tokenServices.setAccessTokenValiditySeconds(-1);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
addUserDetailsService(tokenServices, baseUserDetailsService);
return tokenServices;
}
private void addUserDetailsService(CustomTokenServices tokenServices, BaseUserDetailsService userDetailsService) {
if (userDetailsService != null) {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
provider.setPreAuthenticatedUserDetailsService(new MyUserDetailsByNameServiceWrapper(userDetailsService));
tokenServices.setAuthenticationManager(new ProviderManager(Arrays.asList(provider)));
}
}
###############添加endpoints.tokenServices###########
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancer())
.tokenServices(tokenServices(endpoints))
.userDetailsService(baseUserDetailsService)
.authenticationManager(authenticationManager)
.reuseRefreshTokens(false)
.exceptionTranslator(new CustomWebResponseExceptionTranslator());
}
自定义 UserDetailsByNameServiceWrapper
public class MyUserDetailsByNameServiceWrapper<T extends Authentication> implements AuthenticationUserDetailsService<T>, InitializingBean {
private BaseUserDetailsService userDetailsService = null;
public MyUserDetailsByNameServiceWrapper() {
}
public MyUserDetailsByNameServiceWrapper(BaseUserDetailsService userDetailsService) {
Assert.notNull(userDetailsService, "userDetailsService cannot be null.");
this.userDetailsService = userDetailsService;
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(this.userDetailsService, "UserDetailsService must be set");
}
public UserDetails loadUserDetails(T authentication) throws UsernameNotFoundException {
AbstractAuthenticationToken principal = (AbstractAuthenticationToken) authentication.getPrincipal();
Map<String,String> map = (Map<String, String>) principal.getDetails();
String user_type = map.get("user_type");
return this.userDetailsService.loadUserByLoginName(authentication.getName().split("@")[1],user_type);
}
public void setUserDetailsService(BaseUserDetailsService aUserDetailsService) {
this.userDetailsService = aUserDetailsService;
}
}
自定义 DefaultTokenServices 拷贝
public class CustomTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {
......拷贝DefaultTokenServices代码
登录方式
http://localhost:9999/auth/oauth/token?username=admin&randomCode=g7a4&randomStr=452f9aa0-7dd2-4615-a53b-6c3d5be3b36b&grant_type=password&user_type=admin&password=1234561
三 细节处理:
1.原 MobileAuthFilter 的setDetails 需要自己封装参数
private void setDetails(HttpServletRequest request,
MobileAuthToken authRequest) {
Map<String,String> map = new LinkedHashMap<String, String>();
Enumeration paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()){
String paramName = (String) paramNames.nextElement();
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() != 0) {
map.put(paramName, paramValue);
}
}
}
authRequest.setDetails(map);
}
网友评论