2017-01-23 69 views
1

我很新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()方法。

但我絕對不確定它。如何工作?我錯過了什麼?

回答

2

你可能需要再@AuthenticationPrincipal註釋:

@RequestMapping(value = "/login", method = RequestMethod.POST) 
public ResponseEntity<String> login(@AuthenticationPrincipal CustomUserDetails userInfo) { 

    System.out.println("login() START"); 

    return ResponseEntity.ok("LOGGED IN"); 
} 

如果仍然不能解決問題,請嘗試使用老方法調試:

@RequestMapping(value = "/login", method = RequestMethod.POST) 
public ResponseEntity<String> login() { 

    CustomUserDetails userInfo = (CustomerUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal(); 
    ... 
}  
相關問題