Spring Security Basic Authentication – Spring Security基本认证

最后修改: 2013年 6月 1日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This tutorial will explain how to set up, configure, and customize Basic Authentication with Spring. We’re going to build on top of the simple Spring MVC example, and secure the UI of the MVC application with the Basic Auth mechanism provided by Spring Security.

本教程将解释如何设置、配置和自定义使用 Spring 的基本验证。我们将在简单的Spring MVC 示例的基础上,利用 Spring Security 提供的 Basic Auth 机制来保护 MVC 应用程序的 UI。

2. The Spring Security Configuration

2.Spring安全配置

We can configure Spring Security using Java config:

我们可以使用Java配置来配置Spring Security。

@Configuration
@EnableWebSecurity
public class CustomWebSecurityConfigurerAdapter {

    @Autowired private MyBasicAuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("user1")
          .password(passwordEncoder().encode("user1Pass"))
          .authorities("ROLE_USER");
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/securityNone")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic()
            .authenticationEntryPoint(authenticationEntryPoint);
        http.addFilterAfter(new CustomFilter(), BasicAuthenticationFilter.class);
        return http.build();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Here we’re using the httpBasic() element to define Basic Authentication inside the SecurityFilterChain bean.

这里我们使用httpBasic()元素来定义SecurityFilterChainbean内的基本认证。

We could achieve the same result using XML as well:

我们也可以用XML实现同样的结果。

<http pattern="/securityNone" security="none"/>
<http use-expressions="true">
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <http-basic />
</http>

<authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user1" password="{noop}user1Pass" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

What’s relevant here is the <http-basic> element inside the main <http> element of the configuration. This is enough to enable Basic Authentication for the entire application. Since we’re not focusing on the Authentication Manager in this tutorial, we’ll use an in-memory manager with the user and password defined in plain text.

这里相关的是配置的主<http>元素里面的<http>元素。这足以为整个应用程序启用基本认证。由于我们在本教程中不关注认证管理器,我们将使用一个内存管理器,用户和密码用纯文本定义。

The web.xml of the web application enabling Spring Security has already been discussed in the Spring Logout tutorial.

Spring Logout 教程中已经讨论了启用 Spring Security 的 Web 应用程序的 web.xml

3. Consuming the Secured Application

3.消耗安全的应用程序

The curl command is our go-to tool for consuming the secured application.

curl命令是我们消费安全应用程序的首选工具。

First, let’s try to request the /homepage.html without providing any security credentials:

首先,让我们尝试请求/homepage.html,而不提供任何安全凭证。

curl -i http://localhost:8080/spring-security-rest-basic-auth/api/foos/1

We get back the expected 401 Unauthorized and the Authentication Challenge:

我们得到预期的401 Unauthorized认证挑战

HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E5A8D3C16B65A0A007CFAACAEEE6916B; Path=/spring-security-mvc-basic-auth/; HttpOnly
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Wed, 29 May 2013 15:14:08 GMT

Normally the browser would interpret this challenge and prompt us for credentials with a simple dialog, but since we’re using curl, this isn’t the case.

通常情况下,浏览器会解释这个挑战,并通过一个简单的对话框提示我们的证书,但由于我们使用的是curl,所以情况并非如此。

Now let’s request the same resource, the homepage, but provide the credentials to access it as well:

现在让我们请求同样的资源,即主页,但提供访问它的凭证

curl -i --user user1:user1Pass 
  http://localhost:8080/spring-security-rest-basic-auth/api/foos/1

As a result, the response from the server is 200 OK along with a Cookie:

结果,服务器的响应是200 OK以及一个Cookie

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=301225C7AE7C74B0892887389996785D; Path=/spring-security-mvc-basic-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Wed, 29 May 2013 15:19:38 GMT

From the browser, we can consume the application normally; the only difference is that a login page is no longer a hard requirement since all browsers support Basic Authentication, and use a dialog to prompt the user for credentials.

从浏览器中,我们可以正常使用该应用程序;唯一的区别是,登录页面不再是硬性要求,因为所有的浏览器都支持基本认证,并使用对话框来提示用户的凭证。

4. Further Configuration – the Entry Point

4.进一步的配置–进入点

By default, the BasicAuthenticationEntryPoint provisioned by Spring Security returns a full page for a 401 Unauthorized response back to the client. This HTML representation of the error renders well in a browser. Conversely, it’s not well suited for other scenarios, such as a REST API where a json representation may be preferred.

默认情况下,Spring Security提供的BasicAuthenticationEntryPoint会将401 Unauthorized响应的完整页面返回给客户端。这个错误的HTML表示法在浏览器中的渲染效果很好。相反,它不太适合其他场景,例如REST API,那里可能更喜欢用json表示。

The namespace is flexible enough for this new requirement as well.  To address this, the entry point can be overridden:

命名空间对于这个新的要求也是足够灵活的。 为了解决这个问题,入口点可以被重写。

<http-basic entry-point-ref="myBasicAuthenticationEntryPoint" />

The new entry point is defined as a standard bean:

新的入口点被定义为一个标准的豆子。

@Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {

    @Override
    public void commence(
      HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) 
      throws IOException, ServletException {
        response.addHeader("WWW-Authenticate", "Basic realm="" + getRealmName() + """);
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        PrintWriter writer = response.getWriter();
        writer.println("HTTP Status 401 - " + authEx.getMessage());
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        setRealmName("Baeldung");
        super.afterPropertiesSet();
    }
}

By writing directly to the HTTP Response, we now have full control over the format of the response body.

通过直接写入HTTP响应,我们现在可以完全控制响应体的格式。

5. The Maven Dependencies

5.Maven的依赖性

The Maven dependencies for Spring Security have been discussed before in the Spring Security with Maven article. We will need both spring-security-web and spring-security-config available at runtime.

Spring Security with Maven文章中已经讨论过Spring Security的Maven依赖性。我们将需要在运行时提供spring-security-webspring-security-config

6. Conclusion

6.结论

In this article, we secured an MVC application with Spring Security and Basic Authentication. We discussed the XML configuration, and we consumed the application with simple curl commands. Finally, we took control of the exact error message format, moving from the standard HTML error page to a custom text or JSON format.

在这篇文章中,我们用Spring Security和Basic Authentication保护了一个MVC应用程序。我们讨论了XML配置,并通过简单的curl命令来消耗应用程序。最后,我们控制了确切的错误信息格式,从标准的HTML错误页面转移到自定义的文本或JSON格式。

The full implementation of this article can be found in the GitHub project. This is a Maven-based project, so it should be easy to import and run as it is.

本文的完整实现可以在GitHub项目中找到。这是一个基于Maven的项目,所以应该很容易导入并按原样运行。

When the project runs locally, the sample HTML can be accessed at:

当项目在本地运行时,可以通过以下网址访问样本HTML。

http://localhost:8080/spring-security-rest-basic-auth/api/foos/1.

http://localhost:8080/spring-security-rest-basic-auth/api/foos/1