我需要具有两个不同登录/注册端点的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"
}
如何进行这项工作? 谢谢您的帮助
答案 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