美文网首页
问题记录:SpringSecurity用不同的UserDetai

问题记录:SpringSecurity用不同的UserDetai

作者: 皮皮铭 | 来源:发表于2021-04-07 17:32 被阅读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);
        }
    }
    

    相关文章

      网友评论

          本文标题:问题记录:SpringSecurity用不同的UserDetai

          本文链接:https://www.haomeiwen.com/subject/izmukltx.html