使用 Spring security Javaconfig 进行基本和基于表单的身份验证
Posted
技术标签:
【中文标题】使用 Spring security Javaconfig 进行基本和基于表单的身份验证【英文标题】:Basic and form based authentication with Spring security Javaconfig 【发布时间】:2013-09-14 19:15:43 【问题描述】:我正在尝试为不同的 url 模式定义两种不同的安全配置,其中一种使用表单登录,另一种使用 api 的基本身份验证。
我正在寻找的解决方案类似于此处解释的解决方案http://meera-subbarao.blogspot.co.uk/2010/11/spring-security-combining-basic-and.html,但我想使用 java config 来完成。
提前致谢。
这是我目前的配置:
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserService userService;
@Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userService);
@Override
public void configure(WebSecurity web) throws Exception
// Ignore any request that starts with "/resources/".
web.ignoring().antMatchers("/resources/**");
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin()
.loginUrl("/login")
.failureUrl("/login-error")
.loginProcessingUrl("/security_check")
.usernameParameter("j_username").passwordParameter("j_password")
.permitAll();
http.logout().logoutUrl("/logout");
http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
@Bean
public RememberMeServices rememberMeServices()
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("password", userService);
rememberMeServices.setCookieName("cookieName");
rememberMeServices.setParameter("rememberMe");
return rememberMeServices;
【问题讨论】:
你看到了什么结果? 目前我只有表单身份验证,我找不到如何将基本身份验证添加到 /api/* 之类的 url 模式 【参考方案1】:显然,随着 Spring 的更新,它们的适用性往往会逐渐减弱。运行 spring cloud starter security 1.4.0.RELEASE 这是我的解决方案。我的用例有点不同,因为我尝试使用基本身份验证进行云配置并使用带有 spring 会话的网关在所有其他实例中通过身份验证来保护刷新端点。
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
public void configureGlobal1(AuthenticationManagerBuilder auth) throws Exception
//try in memory auth with no users to support the case that this will allow for users that are logged in to go anywhere
auth.inMemoryAuthentication();
@Override
protected void configure(HttpSecurity http) throws Exception
http
.httpBasic()
.disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable();
@Bean
public BCryptPasswordEncoder encoder()
return new BCryptPasswordEncoder(11);
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
@Autowired
private AuthenticationProvider customAuthenticationProvider;
@Autowired
protected void configureGlobal2(AuthenticationManagerBuilder auth) throws Exception
auth
.authenticationProvider(customAuthenticationProvider);
@Override
protected void configure(HttpSecurity http) throws Exception
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/refresh").hasRole("SUPER")
.and()
.csrf().disable();
请参阅 spring 安全文档以获得进一步说明:Spring Security
基本思想是@Order 注释将指示身份验证方案的运行顺序。没有@Order 意味着它是最后一个。如果 authorizeRequests() 部分无法匹配传入的 URL,则该配置将通过,下一个将尝试身份验证。这将一直持续到身份验证成功或失败。
【讨论】:
【参考方案2】:这里的其他答案相对较旧,例如我在 Spring 4 中找不到authorizeUrls
。
在 SpringBoot 1.4.0 / Spring 4 中,我已经实现了这样的基本/表单登录:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
protected void configure (HttpSecurity aHttp) throws Exception
aHttp.authorizeRequests ().antMatchers (("/api/**")).fullyAuthenticated ().and ().httpBasic ();
aHttp.formLogin ()
.loginPage ("/login").permitAll ()
.and ().logout ().permitAll ();
可能有更优雅的方式来编写这个 - 我仍在努力了解这个构建器是如何在序列等方面工作的。但这行得通。
【讨论】:
这对我不起作用 - 访问 /api/ 的尝试被重定向到登录表单而不是基本身份验证。 @JamesBaker - OP 从来没有提到他需要被提示进行基本身份验证......但是基本身份验证,上面的,确实有效。如果您使用 HTTP 客户端并在您的请求中发送基本身份验证凭据,它确实有效。【参考方案3】:您可以通过在第一个配置中的 http
之后添加 .antMatcher("/api/**")
来解决此问题,以仅管理 /api
网址。您必须在第一个适配器上安装它:
http
.antMatcher("/api/*")
.authorizeRequests()
.antMatchers("^/api/.+$").hasRole("ADMIN")
....
【讨论】:
【参考方案4】:我找到的解决方案是在第一个类中创建另一个扩展 WebSecurityConfigurerAdapter 的类,如https://github.com/spring-projects/spring-security-javaconfig/blob/master/samples-web.md#sample-multi-http-web-configuration 所述
我的解决方法如下:
@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserService userService;
@Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userService);
@Override
public void configure(WebSecurity web) throws Exception
// Ignore any request that starts with "/resources/".
web.ignoring().antMatchers("/resources/**");
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin()
.loginUrl("/login")
.failureUrl("/login-error")
.loginProcessingUrl("/security_check")
.usernameParameter("j_username").passwordParameter("j_password")
.permitAll();
http.logout().logoutUrl("/logout");
http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
@Bean
public RememberMeServices rememberMeServices()
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("password", userService);
rememberMeServices.setCookieName("cookieName");
rememberMeServices.setParameter("rememberMe");
return rememberMeServices;
@Configuration
@Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
@Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication().withUser("api").password("pass").roles("API");
protected void configure(HttpSecurity http) throws Exception
http.authorizeUrls()
.antMatchers("/api/**").hasRole("API")
.and()
.httpBasic();
【讨论】:
【参考方案5】:我会说只是这样做。使用 authorizeUrls() 指定第二行,但用于基本身份验证所需的 URL。而不是formLogin()
使用httpBasic()
@Override
protected void configure(HttpSecurity http) throws Exception
http.authorizeUrls().antMatchers("/", "/index", "/user/**", "/about").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and().formLogin()
.loginUrl("/login")
.failureUrl("/login-error")
.loginProcessingUrl("/security_check")
.usernameParameter("j_username").passwordParameter("j_password")
.permitAll();
http.authorizeUrls().antMatchers("/api/*").hasRole("YOUR_ROLE_HERE").and().httpBasic();
http.logout().logoutUrl("/logout");
http.rememberMe().rememberMeServices(rememberMeServices()).key("password");
类似的东西应该可以。
链接:HttpSecurity
、HttpBasicConfgurer
。
【讨论】:
没用,api 声称两次调用 authorizeUrls() 会覆盖之前的调用,因此可能无法这样做以上是关于使用 Spring security Javaconfig 进行基本和基于表单的身份验证的主要内容,如果未能解决你的问题,请参考以下文章
Spring Framework,Spring Security - 可以在没有 Spring Framework 的情况下使用 Spring Security?
仅使用 Spring-Security(或)Spring 进行授权
在使用 Oauth、SAML 和 spring-security 的多租户的情况下从 spring-security.xml 中获取错误
Spring security:Spring security 如何在 SessionRegistry 中注册新会话?
未调用 Spring Security j_spring_security_check
使用 spring-session 和 spring-cloud-security 时,OAuth2ClientContext (spring-security-oauth2) 不会保留在 Redis