具有两个身份验证的Spring Boot应用程序。 AuthenticationManager bean问题

时间:2020-06-04 02:12:57

标签: java spring-boot spring-security jwt

我需要具有两个不同登录/注册端点的Spring Boot应用,一个是api / user / auth / registerUser和api / node / auth / registerNode。

我编写了代码,但是现在我有两个authenticationManagerBean参见配置:

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration {

    @Configuration
    @Order(1)
    public class SecurityConfig1 extends WebSecurityConfigurerAdapter {

        @Autowired
        CustomUserDetailsService customUserDetailsService;

        @Autowired
        private JwtAuthenticationEntryPoint unauthorizedHandler;

        @Bean
        public JwtAuthenticationFilter jwtAuthenticationFilter() {
            return new JwtAuthenticationFilter();
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder
                    .userDetailsService(customUserDetailsService)
                    .passwordEncoder(passwordEncoder());
        }

        @Bean("authenticationManager")
        @Qualifier("authenticationManager")
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/",
                            "/favicon.ico",
                            "/**/*.png",
                            "/**/*.gif",
                            "/**/*.svg",
                            "/**/*.jpg",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.js")
                    .permitAll()
                    .antMatchers("/api/user/auth/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated();

            // Add our custom JWT security filter
            http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    }

    @Configuration
    @Order(2)
    public class SecurityConfig2 extends WebSecurityConfigurerAdapter {

        @Autowired
        CustomUser1DetailsService customUser1DetailsService;

        @Autowired
        private JwtAuthenticationEntryPoint1 unauthorizedHandler1;

        @Bean
        public JwtAuthenticationFilter1 jwtAuthenticationFilter1() {
            return new JwtAuthenticationFilter1();
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder1) throws Exception {
            authenticationManagerBuilder1
                    .userDetailsService(customUser1DetailsService)
                    .passwordEncoder(passwordEncoder1());
        }

        @Bean("authenticationManager1")
        @Qualifier("authenticationManager1")
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Bean
        public PasswordEncoder passwordEncoder1() {
            return new BCryptPasswordEncoder();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler1)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/",
                            "/favicon.ico",
                            "/**/*.png",
                            "/**/*.gif",
                            "/**/*.svg",
                            "/**/*.jpg",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.js")
                    .permitAll()
                    .antMatchers("/api/node/auth/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated();

            // Add our custom JWT security filter
            http.addFilterBefore(jwtAuthenticationFilter1(), UsernamePasswordAuthenticationFilter.class);
        }
    }
}

然后我成为用户控制者:

@RestController
@RequestMapping("/api/user/auth")
public class UserAuthController {

    @Autowired
    private  UserRepository userRepository;

    @Autowired
    private  RoleRepository roleRepository;

    @Autowired
    private  PasswordEncoder passwordEncoder;

    @Autowired
    @Qualifier("authenticationManager")
    private  AuthenticationManager authenticationManager;

    @Autowired
    private  JwtTokenProvider tokenProvider;

    public UserAuthController() {
    }

    @PostMapping(path = "/registerUser")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if (userRepository.existsByEmail(signUpRequest.getEmail())) {
            return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
        }

        if (userRepository.existsByUsername(signUpRequest.getUsername())) {
            return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
        }

        // Creating User
        User user = new User(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
                signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());

//      Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Set<Role> rules = new HashSet<>();
//      rules.add(userRole);
//      rules.add(adminRole);
//      user.setRoles(rules);

        User result = userRepository.save(user);

        return ResponseEntity.ok(result);
    }

    @PostMapping("/authenticateUser")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        try {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.getUsernameOrEmail(),
                        loginRequest.getPassword()
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String accessToken = tokenProvider.generateAccessToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider.getIssuedDateFromAccessToken(accessToken),tokenProvider.getExpirationDateFromAccessToken(accessToken)));
        } catch (BadCredentialsException exception) {
            throw new BadRequestException("Wrong username or password!");
        }
    }

}

和节点控制器:

@RestController
@RequestMapping("/api/node/auth")
public class NodeAuthController {

    @Autowired
    private User1Repository user1Repository;

    @Autowired
    private Role1Repository role1Repository;

    @Autowired
    private  PasswordEncoder passwordEncoder;

    @Autowired
    @Qualifier("authenticationManager1")
    private  AuthenticationManager authenticationManager1;

    @Autowired
    private JwtTokenProvider1 tokenProvider1;

    @PostMapping(path = "/registerNode")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if (user1Repository.existsByEmail(signUpRequest.getEmail())) {
            return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
        }

        if (user1Repository.existsByUsername(signUpRequest.getUsername())) {
            return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
        }

        // Creating User
        User1 user1 = new User1(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
                signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());

//      Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Set<Role> rules = new HashSet<>();
//      rules.add(userRole);
//      rules.add(adminRole);
//      user.setRoles(rules);

        User1 result = user1Repository.save(user1);

        return ResponseEntity.ok(result);
    }

    @PostMapping("/authenticateNode")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        try {
        Authentication authentication = authenticationManager1.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.getUsernameOrEmail(),
                        loginRequest.getPassword()
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String accessToken = tokenProvider1.generateAccessToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider1.getIssuedDateFromAccessToken(accessToken),tokenProvider1.getExpirationDateFromAccessToken(accessToken)));
        } catch (BadCredentialsException exception) {
            throw new BadRequestException("Wrong username or password!");
        }
    }

}

错误是:java.lang.RuntimeException:java.lang.IllegalArgumentException:找到2个类型为接口org.springframework.security.authentication.AuthenticationManager的bean,但没有将其标记为主要

如果我运行了一个主代码,但对于不是主要响应的控制器,则是

{
    "timestamp": "2020-06-04T03:45:45.638+02:00",
    "status": 401,
    "error": "Unauthorized",
    "message": "",
    "path": "/api/node/auth/registerNode"
}

如何进行这项工作? 谢谢您的帮助

2 个答案:

答案 0 :(得分:1)

以下实现的类似要求对我有效:

@Configuration
@EnableWebSecurity
public class ServerSecurityConfig {

    @Configuration
    @Order(1)
public static class CustomAutorizeURLSecurityConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    @Qualifier("sudoUserDetailsService")
    private UserDetailsService sudoUserDetailsService;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(sudoUserDetailsService);
    }

    @Override
        protected void configure(HttpSecurity http) throws Exception {
             http.antMatcher("/oauth/custom_authorize")
            .csrf().disable()
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .httpBasic()
            ;

            http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER);
    }
}

@Configuration
    @Order(2)
@Import(Encoders.class)
public static class OtherURLSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("customUserDetailsService")
    private UserDetailsService customUserDetailsService;

    @Autowired
    private PasswordEncoder userPasswordEncoder;

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(userPasswordEncoder);
    }

    @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/shutdown").permitAll()
                .antMatchers("/health").permitAll()
                .antMatchers("/info").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/login")
                .permitAll()
            ;

            http
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.NEVER);
    }
}
}

它实现了2种身份验证机制-1)基本身份验证和2)表单登录身份验证

答案 1 :(得分:0)

我的配置:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration{

    @Configuration
    @Order(1)
    public static class SecurityConfig1 extends WebSecurityConfigurerAdapter {

        @Autowired
        @Qualifier("customUserDetailsService")
        CustomUserDetailsService customUserDetailsService;

        @Autowired
        private JwtAuthenticationEntryPoint unauthorizedHandler;

        @Bean
        public JwtAuthenticationFilter jwtAuthenticationFilter() {
            return new JwtAuthenticationFilter();
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder
                    .userDetailsService(customUserDetailsService)
                    .passwordEncoder(passwordEncoder());
        }

        @Bean()
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/",
                            "/favicon.ico",
                            "/**/*.png",
                            "/**/*.gif",
                            "/**/*.svg",
                            "/**/*.jpg",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.js")
                    .permitAll()
                    .antMatchers("/api/user/auth/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated();

            // Add our custom JWT security filter
            http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    }

    @Configuration
    @Order(2)
    public static class SecurityConfig2 extends WebSecurityConfigurerAdapter {

        @Autowired
        @Qualifier("customUser1DetailsService")
        CustomUser1DetailsService customUser1DetailsService;

        @Autowired
        private JwtAuthenticationEntryPoint1 unauthorizedHandler1;

        @Bean
        public JwtAuthenticationFilter1 jwtAuthenticationFilter1() {
            return new JwtAuthenticationFilter1();
        }

        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder1) throws Exception {
            authenticationManagerBuilder1
                    .userDetailsService(customUser1DetailsService)
                    .passwordEncoder(passwordEncoder1());
        }

        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }

        @Bean
        public PasswordEncoder passwordEncoder1() {
            return new BCryptPasswordEncoder();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler1)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/",
                            "/favicon.ico",
                            "/**/*.png",
                            "/**/*.gif",
                            "/**/*.svg",
                            "/**/*.jpg",
                            "/**/*.html",
                            "/**/*.css",
                            "/**/*.js")
                    .permitAll()
                    .antMatchers("/api/node/auth/**")
                    .permitAll()
                    .anyRequest()
                    .authenticated();

            // Add our custom JWT security filter
            http.addFilterBefore(jwtAuthenticationFilter1(), UsernamePasswordAuthenticationFilter.class);
        }
    }
}

和我的用户控制器:

@RestController
@RequestMapping("/api/user/auth")
public class UserAuthController {

    @Autowired
    private  UserRepository userRepository;

    @Autowired
    private  RoleRepository roleRepository;

    @Autowired
    private  PasswordEncoder passwordEncoder;

    @Autowired
    private  AuthenticationManager authenticationManager; //problem is here 

    @Autowired
    private  JwtTokenProvider tokenProvider;

    public UserAuthController() {
    }

    @PostMapping(path = "/registerUser")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if (userRepository.existsByEmail(signUpRequest.getEmail())) {
            return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
        }

        if (userRepository.existsByUsername(signUpRequest.getUsername())) {
            return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
        }

        // Creating User
        User user = new User(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
                signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());

//      Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Set<Role> rules = new HashSet<>();
//      rules.add(userRole);
//      rules.add(adminRole);
//      user.setRoles(rules);

        User result = userRepository.save(user);

        return ResponseEntity.ok(result);
    }

    @PostMapping("/authenticateUser")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        try {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.getUsernameOrEmail(),
                        loginRequest.getPassword()
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String accessToken = tokenProvider.generateAccessToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider.getIssuedDateFromAccessToken(accessToken),tokenProvider.getExpirationDateFromAccessToken(accessToken)));
        } catch (BadCredentialsException exception) {
            throw new BadRequestException("Wrong username or password!");
        }
    }

}

节点控制器:

@RestController
@RequestMapping("/api/node/auth")
public class NodeAuthController {

    @Autowired
    private User1Repository user1Repository;

    @Autowired
    private Role1Repository role1Repository;

    @Autowired
    private  PasswordEncoder passwordEncoder;

    @Autowired
    private  AuthenticationManager authenticationManager1;

    @Autowired
    private JwtTokenProvider1 tokenProvider1;

    @PostMapping(path = "/registerNode")
    public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
        if (user1Repository.existsByEmail(signUpRequest.getEmail())) {
            return new ResponseEntity(new ApiResponse(false, "Email Address already taken"), HttpStatus.BAD_REQUEST);
        }

        if (user1Repository.existsByUsername(signUpRequest.getUsername())) {
            return new ResponseEntity(new ApiResponse(false, "Username already taken"), HttpStatus.BAD_REQUEST);
        }

        // Creating User
        User1 user1 = new User1(signUpRequest.getUsername(), signUpRequest.getEmail(), passwordEncoder.encode(signUpRequest.getPassword()),
                signUpRequest.getFirstName(), signUpRequest.getMiddleName(), signUpRequest.getLastName());

//      Role userRole = roleRepo.findByName(RoleName.ROLE_USER)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Role adminRole = roleRepo.findByName(RoleName.ROLE_ADMIN)
//              .orElseThrow(() -> new AppException("User Role not set."));
//
//      Set<Role> rules = new HashSet<>();
//      rules.add(userRole);
//      rules.add(adminRole);
//      user.setRoles(rules);

        User1 result = user1Repository.save(user1);

        return ResponseEntity.ok(result);
    }

    @PostMapping("/authenticateNode")
    public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
        try {
        Authentication authentication = authenticationManager1.authenticate(
                new UsernamePasswordAuthenticationToken(
                        loginRequest.getUsernameOrEmail(),
                        loginRequest.getPassword()
                )
        );
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String accessToken = tokenProvider1.generateAccessToken(authentication);
        return ResponseEntity.ok(new JwtAuthenticationResponse(accessToken,tokenProvider1.getIssuedDateFromAccessToken(accessToken),tokenProvider1.getExpirationDateFromAccessToken(accessToken)));
        } catch (BadCredentialsException exception) {
            throw new BadRequestException("Wrong username or password!");
        }
    }

}

如果我在其中一个bean上添加@Primary,并且具有不同名称代码的bean正常工作,但仅对于主bean,另一个bean不使用ant vot,则控制器身份验证是错误的。 如果没有@Primary注释,则会出现错误:java.lang.RuntimeException:java.lang.IllegalArgumentException:找到2个类型为org.springframework.security.authentication.AuthenticationManager接口的bean,但没有将其标记为primary

相关问题