我正在使用spring-webmvc 4.07版和Spring Security v 3.2查看一個簡單的Spring引導項目。基本的安全配置與以下配置類,以提供安全的URL和一個自定義的UserDetails實現重寫:將UserDetails傳遞給彈簧控制器
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").access("hasRole('READER')")
.antMatchers("/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true");
}
@Override
protected void configure(
AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserDetails userDetails = readerRepository.findOne(username);
if (userDetails != null) {
return userDetails;
}
throw new UsernameNotFoundException("User '" + username + "' not found.");
}
});
}
}
上述readerRepository.findOne(用戶名),是基於在接口上
public interface ReaderRepository extends JpaRepository<Reader, String> {
List<Book> findByReader(String reader);
}
所以它正在使用登錄頁面上提供的用戶名在數據庫中尋找Reader。 Reader類是
@Entity
public class Reader implements UserDetails {
private static final long serialVersionUID = 1L;
@Id
private String username;
private String fullname;
private String password;
...Setters/Getters, getAuthorities(), isAccountNonExpired(), isAccountNonLocked(), isCredentialsNonExpired(), isEnabled()
}
有一個控制器,
@Controller
@RequestMapping("/")
@ConfigurationProperties("amazon")
public class ReadingListController {
private ReadingListRepository readingListRepository;
private AmazonProperties amazonConfig;
@Autowired
public ReadingListController(ReadingListRepository readingListRepository,
AmazonProperties amazonConfig) {
this.readingListRepository = readingListRepository;
this.amazonConfig = amazonConfig;
}
@RequestMapping(method=RequestMethod.GET)
public String readersBooks(Reader reader, Model model) {
List<Book> readingList = readingListRepository.findByReader(reader);
if (readingList != null) {
model.addAttribute("books", readingList);
model.addAttribute("reader", reader);
model.addAttribute("amazonID", amazonConfig.getAssociateId());
}
return "readingList";
}
@RequestMapping(method=RequestMethod.POST)
public String addToReadingList(Reader reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/";
}
}
我運行命令 「gradle這個bootrun」 的應用程序。當我去localhost:8080 /我會看到一個登錄頁面。當我登錄時,控制器的readerBooks(...)方法被調用。此方法具有一個Reader對象作爲參數,其中包含已登錄的讀者,其用戶名已在登錄頁面上輸入。 Reader類(實現UserDetails)顯然被Spring傳入。但是,我從來沒有見過這樣做。我已經看到它通過傳遞用@AuthenticationPrincipal註解的Principal來完成,或者通過訪問控制器方法內的SecurityContext,但我無法找到任何記錄爲什麼在這種情況下Reader被傳入的東西。是因爲Reader實現UserDetails?