我很新Spring Security我有以下问题。 。如何从Spring MVC Boot Controller方法正确检索记录的用户信息?
我正在使用春季安全,以保护所有的资源投入到/外网/”一春引导 prject
所以基本上我WebSecurityConfig配置类包含此代码:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = CustomUserDetailsService.class)
@EnableAutoConfiguration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/Extranet/**").access("hasRole('ROLE_USER')")
.anyRequest().permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();
}
}
它工作正常,事实上访问资源为/Extranet/login我必须设置基本身份验证并指定正确的用户名和密码(使用邮递员工具来执行请求来测试它)。
好吧,这工作正常。
在我的春季安全配置involed这个CustomUserDetails类,它实现了Spring Security的接口的UserDetails。
public class CustomUserDetails extends User implements UserDetails {
private static final long serialVersionUID = 1L;
public CustomUserDetails(User user){
super(user);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
for(UserRole role : this.getUserRoles()){
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(role.getName());
authorities.add(grantedAuthority);
}
return authorities;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public String getUsername() {
return super.getUsername();
}
}
此对象的实例包含当前登录的用户的用户详细信息。
好吧,我的疑问是:我如何从控制器方法检索这个对象? (我认为这应该是在上下文中,我可以以某种方式检索它)。
我已经tryied这样做:
@RestController
@RequestMapping("/Extranet")
public class AccessController {
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<String> login(CustomUserDetails userInfo) {
System.out.println("login() START");
return ResponseEntity.ok("LOGGED IN");
}
}
但这种方式我得到这样一个例外:
[ERROR] 2017-01-23 14:18:04 [com.betrivius.controller.exceptionHandler.ControllerExceptionHandler.handleException(ControllerExceptionHandler.java:106)] [http-nio-8080-exec-1] ControllerExceptionHandler - Request: http://localhost:8080/Extranet/login throws:
org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.betrivius.security.bean.CustomUserDetails]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.betrivius.security.bean.CustomUserDetails.<init>()
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:105) ~[spring-beans-4.3.3.RELEASE.jar:4.3.3.RELEASE]
看来,它不能instantialete的CustomUserDetails目的。为什么?
从我所知我可以检索CustomUserDetails与记录的用户相关的对象。我该怎么做?
我也试着这样做:
@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<String> login(Principal principal) {
System.out.println("login() START");
return ResponseEntity.ok("LOGGED IN");
}
这样的本金参数是否正确实例化,包含以前CustomUserDetails包含登录用户的信息对象的实例。
那么,它是访问当前记录的用户信息的正确方法吗?
另一个疑问是:为什么我可以在此主要本金参数传递给我的登录()方法?究竟发生了什么?谁有效地将它传递给登录()方法?
我认为应该发生这样的事情:
1)有一个POST的HttpRequest朝着“/外网/登录”资源。调度程序servlet将其发送给登录()方法。
2)校长在用户启用此资源之前(在调用控制器方法之前)被放入Spring Context中,因此Spring工厂可以从上下文中检索它并将其传递给login()方法。
但我绝对不确定它。如何工作?我错过了什么?