解决oauth2多类型用户登录

1.拷贝 DaoAuthenticationProvider代码,自定义 MyAuthenticationProvider 继承 AbstractUserDetailsAuthenticationProvider
在retrieveUser方法添加user_type


protected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    this.prepareTimingAttackProtection();
    Map map = (Map) 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 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 implements AuthenticationUserDetailsService, 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 map = (Map) 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 map = new LinkedHashMap();
   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);
}












你可能感兴趣的:(解决oauth2多类型用户登录)