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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有两个身份验证的Spring boot应用。 AuthenticationManager bean问题相关的知识,希望对你有一定的参考价值。

我需要具有两个不同登录/注册端点的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"
}

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

我需要具有两个不同登录/注册端点的Spring Boot应用,其中一个是api / user / auth / registerUser和api / node / auth / registerNode。我写了代码,但是现在我有两个authenticationManagerBean参见...

答案

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

以上是关于具有两个身份验证的Spring boot应用。 AuthenticationManager bean问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 Spring Boot 进行 JWT 身份验证

Spring Boot:使用 Junit 模拟具有安全上下文的用户身份验证

Spring boot 如何让 Thymeleaf 网页和 REST API 具有不同的身份验证方案

具有基本身份验证和 OAuth 顺序问题的 Spring Boot 安全性

具有 OAuth 2 和 JWT 安全性的 Spring Boot 微服务

*已解决*我可以将 Spring Boot 作为具有 Digest 身份验证请求的客户端运行吗?