我正在使用Spring Boot(2.0.1)实现REST API以与MongoDB(3.6)一起使用。我真的卡住了。我还尝试过StackOverFlow的其他提示,但由于某些原因它没有帮助。
我已经将SecurityConfig.java配置为允许访问某些区域,并且还创建了一个用户inMemoryAuthentication,以便能够登录到HAL Browser(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;
// }
}
我已经尝试了不同的方法(注释块),但仍然没有运气。
即使permitAll()
上有/register
,我仍然会收到自动生成的登录表单,该表单不会接受任何凭据。
正如我之前所说,使用我的API的唯一方法是排除SecurityAutoConfiguration(@EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class
),但它不是一个安全选项。
有什么方法可以解决这个问题吗?
答案 0 :(得分:0)
从我所看到的情况来看,你的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
注释(例如@Configuration
),则Spring Boot不会检测类中的注释。 ,@Service
,...)
编辑:我很快就制定了一个程序来模仿你的情况:
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
和任何密码(记住,假密码编码器不关心密码)登录时,它会将我重定向到{{ 1}}并显示以下内容:
/
(这是正常的,因为这是我输出的内容)