我刚开始学习Spring和Spring Security,我通过阅读Spring Security文档创建了一个简单的项目。我完成了以下基于java的配置。
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin")
.password("nimda")
.roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/admin**").access("hasRole('ADMIN')")
.and().formLogin();
http.csrf().disable();
}
}
当我选择" / admin"它将我重定向到我知道使用此默认配置生成的登录页面,登录后它将显示登录页面。现在我的问题是:登录表单发布到" / login"我没有定义任何" AuthenticationManager"和" UserDetailService"我在自定义配置的文档中读到了如何弹出表单并执行登录过程?基本上我想知道这个默认登录过程内部工作的一些细节。
答案 0 :(得分:0)
当您使用* ConfigurerAdapter类时,在上下文加载期间会发生很多事情。 Spring将检查您是否定义了AuthenticationManager,如果没有,它将创建一个默认的。
如果您真的对魔术配置步骤中发生的事情感兴趣,您可能需要查看源代码。例如,如果您查看WebSecurityConfigurerAdapter.getHttp(),您可以看到它调用authenticationManager()以构造此bean。
protected AuthenticationManager authenticationManager() throws Exception {
if (!authenticationManagerInitialized) {
configure(localConfigureAuthenticationBldr);
if (disableLocalConfigureAuthenticationBldr) {
authenticationManager = authenticationConfiguration
.getAuthenticationManager();
}
else {
authenticationManager = localConfigureAuthenticationBldr.build();
}
authenticationManagerInitialized = true;
}
return authenticationManager;
}
在过去,你必须自己创造所有豆子并将它们连接在一起,这样我们就能更清楚地了解事物是如何组合在一起的。现在你要么必须阅读来源,要么从指南中复制,并希望你不要犯任何错误。
调试提示:这些天我查看加载上下文后存在的bean,然后我返回并在AuthenticationManager实现的构造函数中设置断点,然后我可以看到call-stack以及初始化的工作原理。
答案 1 :(得分:0)
以下是您要查找的代码,而不是使用构建器来构建内存中的用户详细信息源,您可以实现自己的自定义AuthenticationProvider。
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(new AuthenticationProvider() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String password = (String) authentication.getPrincipal();
String userName = (String) authentication.getCredentials();
if ("user".equals(userName) && "password".equals(password)) {
authentication = new UsernamePasswordAuthenticationToken(userName, password, Lists.newArrayList(new SimpleListProperty<GrantedAuthority>(null, "USER")));
return authentication;
}
throw new BadCredentialsException("Incorrect username or password.");
}
@Override
public boolean supports(Class<?> authentication) {
return true;
}
});
}
请注意,您可以创建自己的身份验证实施,以备需要添加其他信息时使用,或者您可以使用每个身份验证可以拥有的详细信息属性。