[英]Spring Security 5 / Login / REST API Accessibility / Bad Credentials even if they are right?
我正在使用Spring Boot(2.0.1)实现MongoDB(3.6)的REST API。 我真的被卡住了。 我也尝试了StackOverFlow的其他技巧,但由于某些原因没有帮助。
我已经配置了SecurityConfig.java以允许访问某些区域,并且还创建了一个用户inMemoryAuthentication,以便能够登录到HAL浏览器(Spring)等。但是问题是,无论我在浏览器中输入的任何地址都得到了由于某种原因,登录表单和inMemoryAuthentication中使用的凭据总是错误的。 我发现访问API的唯一方法是在主类中排除SecurityAutoConfiguration。 但这会打开所有权限,无需身份验证即可访问包括HAL浏览器在内的所有内容。
有人会告诉我我做错了吗? 我只想允许所有人使用某些路径/地址,只允许将其他所有内容与TokenAuthentication一起使用(已经对其进行了自定义实现),并且只有一个用户(用户名,密码)访问HAL浏览器。
这是我的SecurityConfig.java:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private final TokenAuthenticationService tokenAuthenticationService;
@Autowired
protected SecurityConfig(final TokenAuthenticationService tokenAuthenticationService) {
super();
this.tokenAuthenticationService = tokenAuthenticationService;
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.addFilterBefore(new TokenAuthenticationFilter(tokenAuthenticationService), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/hello").permitAll()
.antMatchers("/test2").permitAll()
.antMatchers("/register").permitAll()
.antMatchers("/useraccount").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth
// .inMemoryAuthentication()
// .withUser("user1").password("password").roles("ADMIN");
auth
.inMemoryAuthentication()
.withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER"));
// auth
// .userDetailsService(userService);
}
// @Bean
// @Override
// public UserDetailsService userDetailsService() {
// UserDetails user =
// User.withDefaultPasswordEncoder()
// .username("user")
// .password("password")
// .roles("USER")
// .build();
//
// return new InMemoryUserDetailsManager(user);
// }
// @Bean
// public UserDetailsService userDetailsService() {
// InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
// manager.createUser(User.withUsername("user").password("pass").roles("USER", "ADMIN").build());
// return manager;
// }
}
如您所见,我尝试了不同的方法(注释块),但是仍然没有运气。 即使我在/register
上具有permitAll()
,我仍然会获得自动生成的登录表单,该表单将不接受任何凭据。
因此,正如我之前所说,使用我的API的唯一方法是排除SecurityAutoConfiguration( @EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class
),但这不是安全的选择。
有什么办法解决这个问题?
据我所知,您的SecurityConfig
类很可能从未调用,因为它没有任何注释指示Spring Boot应该在类中寻找要自动装配的bean( @Autowired
)
为了给您一个主意,以下内容将永远不会被调用:
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
System.out.println("This will never called");
}
}
而如果我们有@EnableWebSecurity
:
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
System.out.println("This is called");
}
}
请记住,如果类本身未使用@Component
或继承了@Component
注释的其他注释(例如@Service
@Configuration
, @Service
@Component
,...)进行注释,则Spring Boot将不会在类内部检测到注释。
编辑 :我迅速建立了一个程序来模仿您的情况:
SecurityConfiguration.java
:
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser(new User("root", "root", Arrays.asList(new SimpleGrantedAuthority("USER"))))
.passwordEncoder(fakePasswordEncoder());
}
@Bean
public PasswordEncoder fakePasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return null; // matches(...) will always return true anyways
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/hello").permitAll()
.antMatchers("/test2").permitAll()
.antMatchers("/register").permitAll()
.antMatchers("/useraccount").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll();
}
}
请注意,我只是快速制作了一个忽略密码的密码编码器,因为这将需要更多的工作
ExampleController.java
:
@RestController
public class ExampleController {
@GetMapping("/")
public Object index() {
return getCurrentUser();
}
public Object getCurrentUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return ((UsernamePasswordAuthenticationToken)auth).getPrincipal();
}
}
当我使用用户名root
和任何密码登录时( 记住,假密码编码器并不关心密码 ),它会将我重定向到/
并显示以下内容:
{"password":null,"username":"root","authorities":[{"authority":"USER"}],"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true,"enabled":true}
(这是正常的,因为这就是我要输出的内容)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.