我正在使用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?