赞
踩
实现其他系统的用户能够登录到系统B
之前系统A与系统B并无关联,简单说就是分别有一套用户体系,各自有各自的登录功能。
现在需要让系统A的用户使用账号密码也能登录到系统B。
要点:
可以通过用户名的特殊标识、配置(不太现实)、加载本地所有账号、前端传用户类型等等方式来判断当前的登录用户是系统A还是系统B。之后走不同的认证流程。
在系统B中创建一个用户来关联系统A的用户,利用系统B中的用户来管理权限。(同步用户)
项目使用的是spring security,通过扩展spring security 认证机制来实现此功能。(多 provider)
代码:
创建一个远程认证的Provider
// 远程认证 Provider public class RemoteAuthenticationProvider implements AuthenticationProvider { private UserDetailsService userDetailsService; private RemoteService remoteService;// 远程认证服务 public RemoteAuthenticationProvider(){ this.userDetailsService = SpringContextUtil.getBean(UserDetailsService.class); this.remoteService= SpringContextUtil.getBean(RemoteService .class); } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = authentication.getCredentials().toString(); // 本地管理员,不做远程认证 if("admin".equals(username)){ // 此处涉及spring security的认证机制,当前Provider返回null时,则会查找下一个Provider进行认证 return null; } try { // 1、远程验证帐号密码 Object resp = remoteService.verifyPwd(username, password); if(!resp.isSuccess()){ throw new RuntimeException(resp.getMsg()); } // 2、同步用户,便于管理权限 remoteService.syncUserIfNotExist(username); } catch (Exception e) { log.error("远程验证失败", e); throw new InternalAuthenticationServiceException("远程验证失败", e); } UserDetails userDetails = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); return result; } @Override public boolean supports(Class<?> authentication) { return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } }
配置多 Provider,先走远程认证的Provider,再走本地数据库认证的Provider
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { RemoteAuthenticationProvider remoteAuthenticationProvider = new RemoteAuthenticationProvider(); DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(); daoAuthenticationProvider.setUserDetailsService(userDetailsService); daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); // ProviderManager providerManager = new ProviderManager(Collections.singletonList(daoAuthenticationProvider)); // auth.parentAuthenticationManager(providerManager); auth.authenticationProvider(remoteAuthenticationProvider);// 远程认证在前 auth.authenticationProvider(daoAuthenticationProvider);// 本地认证在后 // super.configure(auth); } }
关于 RemoteAuthenticationProvider 中 return null;
的说明:
spring security的认证机制是当前Provider返回null时,则会查找下一个Provider进行认证。所以也能解释在SecurityConfiguration 中把RemoteAuthenticationProvider 放在 DaoAuthenticationProvider 之前,当用户不需要远程认证时,只需要在RemoteAuthenticationProvider 返回null,则会进入DaoAuthenticationProvider进行本地认证。
end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。