问题记录: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);
    }
}
上一篇下一篇

猜你喜欢

热点阅读