问题记录:SpringSecurity用不同的UserDetai
2021-04-07 本文已影响0人
皮皮铭
问题:针对不同情景使用不同 UserService 的实现
自定义 Filter 继承 UsernamePasswordAuthenticationFilter,分别实现AuthenticationManager
解决方案:
configure 配置
.addFilter(new MultipleAuthenticationFilter(storeAuthenticationManager(), "/store/login"))
.addFilter(new MultipleAuthenticationFilter(adminAuthenticationManager(), "/admin/login"));
AuthenticationManager 配置
List<AuthenticationProvider> providers = new ArrayList<>();
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(adminDetailsService()); // or userDetailsService
providers.add(daoAuthenticationProvider);
return new ProviderManager(providers);
代码:
SecurityConfig类
@Component
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AdminDetailsServiceImpl adminDetailsService;
@Autowired
private StoreDetailsServiceImpl storeDetailsService;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(adminDetailsService).passwordEncoder(bCryptPasswordEncoder);
auth.userDetailsService(storeDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.cors().and()
// 由于使用的是JWT,我们这里不需要csrf
.csrf().disable()
.authorizeRequests()
.and()
.addFilter(new StoreJwtLoginFilter(storeAuthenticationManager()))
.addFilter(new AdminJwtLoginFilter(adminAuthenticationManager()))
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 统一处理403请求
.exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint());
}
private AuthenticationManager storeAuthenticationManager() {
List<AuthenticationProvider> providers = new ArrayList<>();
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(storeDetailsService);
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
providers.add(daoAuthenticationProvider);
return new ProviderManager(providers);
}
private AuthenticationManager adminAuthenticationManager() {
List<AuthenticationProvider> providers = new ArrayList<>();
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(adminDetailsService);
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
providers.add(daoAuthenticationProvider);
return new ProviderManager(providers);
}
}
自定义 Filter
public class AdminJwtLoginFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public AdminJwtLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
super.setFilterProcessesUrl("/admin/login");
}
/**
* 接收并解析用户凭证
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
//从输入流中获取到登录的信息
LoginAdmin loginAdmin = new ObjectMapper().readValue(request.getInputStream(), LoginAdmin.class);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginAdmin.getAccount(), loginAdmin.getPassword(), new ArrayList<>()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 用户成功登录后,这个方法会被调用,我们在这个方法里生成token
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException {
JwtAdmin jwtAdmin = (JwtAdmin) auth.getPrincipal();
String token = JwtTokenUtil.createTokenAdmin(jwtAdmin.getId(), jwtAdmin.getUsername(), Arrays.toString(jwtAdmin.getAuthorities().toArray()));
Map<String, String> map = new HashMap<>();
map.put("adminId", jwtAdmin.getId() + "");
map.put("roleId", jwtAdmin.getRoleId() + "");
map.put(JwtTokenUtil.TOKEN_HEADER, JwtTokenUtil.TOKEN_PREFIX + token);
response.setContentType("application/json; charset=utf-8");
response.getWriter().write(GsonUtil.beanToJson(ApiResultUtil.success(map)));
}
/**
* 验证失败时候调用的方法
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException {
response.setContentType("application/json; charset=utf-8");
response.getWriter().write(GsonUtil.beanToJson(ApiResultUtil.error(10999,failed.getMessage())));
}
}
UserDetailsService实现类
@Service
public class AdminDetailsServiceImpl implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) {
OfficialInfo officialInfo = new OfficialInfo();
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
return new JwtAdmin(officialInfo, grantedAuthorities);
}
}