【问题标题】:Different authentication for different "Accept" content type header field不同“接受”内容类型标头字段的不同身份验证
【发布时间】:2017-07-31 22:22:08
【问题描述】:

我有一个简单的 Web 应用程序,它使用默认的 Spring Security 表单身份验证,一旦通过身份验证,用户就可以在 Thymeleaf 视图之间浏览并访问内容。

我能够为 REST 客户端应用程序提供 JSON,而不是 Web 视图,对于同一个端点,只需使用这样的 Spring 映射:

// response for web application, thymeleaf views
@RequestMapping("/fruits", produces = MediaType.TEXT_HTML_VALUE)
public String index(Model model) {
    model.addAttribute("fruits", fruits);
    return "fruitsView";
}

// response for REST client applications
@RequestMapping("/fruits", produces = MediaType.APPLICATION_JSON_VALUE)
public Fruits[] index() {
    return fruits;
}

问题是:当请求接受 JSON(Accept 标头字段)而不是首先接受 HTML 时,是否可以接受基本身份验证而不是使用登录 Web 表单进行响应?

我的安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // works well for web views: 
        http.authorizeRequests().antMatchers("/**").hasRole("USER").and().formLogin();

        // works well for REST clients:
        // http.authorizeRequests().antMatchers("/**").hasRole("USER").and().httpBasic();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
    }

}

是否可以同时配置 httpBasicformLogin 身份验证,以分别响应特定的 Accept 内容类型标头字段?

我了解到对于不同的 URL 模式可以有两种不同的身份验证:Spring REST security - Secure different URLs differently。但是对于同一个 URL 的两种不同的身份验证机制,其中请求由 Accept 内容头字段区分,怎么样?

【问题讨论】:

  • @dur 尝试过.formLogin().and().httpBasic()。通过浏览器访问时,我得到了预期的登录表单。但是在通过其他客户端访问时,将 application/json 作为 Accept 标头字段,如果未通过身份验证,我可以访问内容。
  • @dur 虽然您删除了您的评论,但您是对的:客户端工具是一个浏览器插件,因此它会发送浏览器 cookie。当没有发送 cookie 时,.formLogin().and().httpBasic() 在通过浏览器访问端点时使用表单登录身份验证和 http 基本身份验证非常有效,同时像 REST API 一样使用端点。问题解决了!谢谢!

标签: java spring rest spring-mvc spring-security


【解决方案1】:

就代码的可扩展性和可维护性而言,这可能不是长期运行的好习惯。

但是,这可能会在一定程度上帮助您。但这指向具有两种登录类型的相同资源并提供相同的响应。在您的情况下,您希望为同一资源提供不同的响应。这就是它不是一个好的做法的原因。 Combining basic authentication and form login for the same REST Api

另一种建议是向您的请求添加可选属性,当您根据可选属性值在服务器端到达请求时,调用适当的方法并根据需要设置响应内容类型。

【讨论】:

  • 感谢您花时间发布此内容。但是我想以两种不同的格式提供 same resource,这就是为什么我想通过同一个端点来执行此操作,这就是根据 HTTP 的 Accept 标头字段的目的RFC(参见“内容类型协商”)。这也是 Ruby on Rails 的方式,Spring 通过 RequestMapping 注释明确支持这一点。而且我不明白为什么对同一个端点启用两种不同形式的身份验证会是一种不好的做法。
猜你喜欢
  • 2017-03-26
  • 2020-06-04
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 2020-10-29
相关资源
最近更新 更多