HttpBasic authentication has some limitations and security risks, so it is not often used in actual projects. However, it is sometimes convenient to enable HttpBasic authentication for testing purposes.

So Songo is here to talk briefly about HttpBasic authentication in Spring Security.

This article is the 29th in the Spring Security series, and reading the previous articles will help you understand it better:

  1. Dig a big hole and Spring Security will do it!
  2. How to decrypt the password
  3. A step-by-step guide to customizing form logins in Spring Security
  4. Spring Security does front and back separation, so don’t do page jumps! All JSON interactions
  5. Authorization in Spring Security used to be so simple
  6. How does Spring Security store user data into the database?
  7. Spring Security+Spring Data Jpa, Security management is only easier!
  8. Spring Boot + Spring Security enables automatic login
  9. Spring Boot automatic login. How to control security risks?
  10. How is Spring Security better than Shiro in microservices projects?
  11. Two ways for SpringSecurity to customize authentication logic (advanced play)
  12. How can I quickly view information such as the IP address of the login user in Spring Security?
  13. Spring Security automatically kicks out the previous login user.
  14. How can I kick out a user who has logged in to Spring Boot + Vue?
  15. Spring Security comes with a firewall! You have no idea how secure your system is!
  16. What is a session fixed attack? How do I defend against session fixation attacks in Spring Boot?
  17. How does Spring Security handle session sharing in a clustered deployment?
  18. Songgo hand in hand to teach you in SpringBoot CSRF attack! So easy!
  19. Learn to learn thoroughly! Spring Security CSRF defense source code parsing
  20. Two poses for password encryption in Spring Boot!
  21. How to learn Spring Security? Why must we study systematically?
  22. Spring Security has two different resource release policies. Do not use them incorrectly.
  23. Spring Boot + CAS single sign-on
  24. Spring Boot is the third way to implement single sign-on!
  25. How do I Connect to the Database in Spring Boot+CAS SINGLE Sign-on?
  26. Spring Boot+CAS default login page is too ugly, how to do?
  27. How to carry Token in request header with Swagger
  28. Summary of three cross-domain scenarios in Spring Boot

1. What is HttpBasic

Http Basic authentication is a means of authentication between Web servers and clients, originally defined in the HTTP1.0 specification (RFC 1945), Subsequent security information can be found in the HTTP 1.1 specification (RFC 2616) and HTTP Authentication specification (RFC 2617).

The main advantages of HttpBasic are that it is very simple to use. There is no complex page interaction, only information in the request header is required for authentication, and it is a stateless login, meaning that no user login information is recorded in the session.

The biggest problem with HttpBasic is security, because usernames/passwords are simply Base64 encoded and then transmitted, easily sniffed by tools that expose user information.

Spring Security supports both basic HttpBasic authentication and Http digest authentication. Http digest authentication improves information Security management based on HttpBasic authentication, but also increases code complexity. So Http digest authentication is not used much.

Here, Songo shares both authentication methods in Spring Security.

2. HttpBasic certification

Let’s look at the implementation first and then examine its authentication process.

Start by creating a Spring Boot project that introduces Web and Spring Security dependencies as follows:

Next create a test interface:

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello(a) {
        return "hello"; }}Copy the code

To enable HttpBasic authentication:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .httpBasic(); }}Copy the code

Finally, configure the basic user information in application.properties as follows:

spring.security.user.password=123
spring.security.user.name=javaboy
Copy the code

After the configuration is complete, start the project and access the /hello interface. At this time, the browser will pop up and ask us to enter the user name/password information:

At this point we look at the request response header as follows:

As you can see, the browser responded to 401 with a WWW-Authenticate response header that describes the authentication form. If we were using HttpBasic, the default response header format would look like this.

Next, we input the user name and password and click Sign In to log In. After login, we can access/Hello interface successfully.

We look at the second request as follows:

As you can see, in the request header, there is an additional Authorization field with the value Basic amF2YWJveToxMjM=,

AmF2YWJveToxMjM = is a Base64 encoded string. After decoding the string, we found the following results:

String x = new String(Base64.getDecoder().decode("amF2YWJveToxMjM="), "UTF-8");
Copy the code

The decoding results are as follows:

As you can see, this is our username and password information. The username/password is passed after simple Base64 encoding, so this authentication method is dangerous ⚠️.

Let’s summarize the HttpBasic authentication process a bit:

  1. The browser requests access/helloInterface.
  2. The server returns 401, indicating that it is not authenticated. The wwW-Authenticate field is also carried in the response header to describe the authentication form.
  3. After the browser receives the 401 response, a dialog box is displayed asking the user to enter the user name and password. After the user enters the user name and password, the browser encodes them in Base64 and sends them to the server.
  4. The server decodes the message from the browser, verifies it, and responds to the client when there is no problem.

That’s the general process.

3.Http digest authentication

Http digest authentication is basically compatible with HttpBasic authentication, but is much more complex, not only in the code, but also in the request process.

The most important improvement in Http digest authentication is that it does not send plaintext passwords over the network. Its entire certification process looks like this:

  1. The browser requests access/helloInterface.
  2. The server returns 401, indicating that it is not authenticated, and carries the www-Authenticate field in the response header to describe the authentication form. , the server will calculate a random string, together with the return to the front, so that we can prevent replay attack (sniffing a replay attack is others to your information, send as the password again and again the service side, plus a random string, can change the generated information will change, can prevent replay attack), are as follows:

In addition, the field returned by the server also has a QOP, indicating the protection level, and auth, indicating authentication only. Auth-int indicates that the content is also verified.

Nonce is a random string generated by the server. It is a Base64 encoded string. After decoding, we find that it is composed of expiration time and key. On subsequent requests, the Nonce is sent back to the server intact.

  1. The client selects an algorithm based on which the password and other data summaries are calculated as follows:

As you can see, the client sends a lot of data to the server.

  • A nonce is a random string sent from the server.
  • Response is the generated summary information.
  • Nc indicates that at this time of request, replay attacks can be prevented.
  • Cnonce represents a random string sent by the client to the server.
  1. The server can query the user password according to the user name sent by the client, and then calculate the summary information according to the user password, and then compare the summary information with the summary information sent by the client to confirm the user identity.

That’s the whole process.

In a word, the original user password was replaced by the information, for the sake of safety, the information will change according to the random string of server returns, the server according to user’s password, also calculate a password information, and then, comparing the information from the client and no problem, if the user if authentication was successful. Of course, some expiration restrictions and replay attack defense mechanisms are added on this basis.

Ok, so how does this work in Spring Security code?

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(digestAuthenticationEntryPoint())
                .and()
                .addFilter(digestAuthenticationFilter());
    }

    @Bean
    DigestAuthenticationEntryPoint digestAuthenticationEntryPoint(a) {
        DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
        entryPoint.setKey("javaboy");
        entryPoint.setRealmName("myrealm");
        entryPoint.setNonceValiditySeconds(1000);
        return entryPoint;
    }
    @Bean
    DigestAuthenticationFilter digestAuthenticationFilter(a) {
        DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
        filter.setAuthenticationEntryPoint(digestAuthenticationEntryPoint());
        filter.setUserDetailsService(userDetailsService());
        return filter;
    }

    @Override
    @Bean
    protected UserDetailsService userDetailsService(a) {
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
        manager.createUser(User.withUsername("javaboy").password("123").roles("admin").build());
        return manager;
    }

    @Bean
    PasswordEncoder passwordEncoder(a) {
        returnNoOpPasswordEncoder.getInstance(); }}Copy the code

Configuration is nothing more than two aspects, one is the server random string generation, the other is the client summary information verification.

  1. First provide DigestAuthenticationEntryPoint instance, configuration server random Numbers generated by a write parameters, such as the nonce valid for how long (will be), the name of the realm, and the key needed for the nonce. Specific nonce generation logic in DigestAuthenticationEntryPoint# commence method:
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
	HttpServletResponse httpResponse = response;
	long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000);
	String signatureValue = DigestAuthUtils.md5Hex(expiryTime + ":" + key);
	String nonceValue = expiryTime + ":" + signatureValue;
	String nonceValueBase64 = new String(Base64.getEncoder().encode(nonceValue.getBytes()));
	String authenticateHeader = "Digest realm=\"" + realmName + "\","
			+ "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\" ";
	if (authException instanceof NonceExpiredException) {
		authenticateHeader = authenticateHeader + ", stale=\"true\"";
	}
	if (logger.isDebugEnabled()) {
		logger.debug("WWW-Authenticate header sent to user agent: "
				+ authenticateHeader);
	}
	httpResponse.addHeader("WWW-Authenticate", authenticateHeader);
	httpResponse.sendError(HttpStatus.UNAUTHORIZED.value(),
		HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
Copy the code

In this code, the expiration time is first obtained, and then the expiration time and key are combined to calculate the message digest. Then nonce and message digest are used as value to calculate a Base64 encoding character, and the encoding character is written back to the front end.

  1. Configuration DigestAuthenticationFilter filter, mainly used to handle the front-end request. Filter source code is long, I will not post here, a core idea is to get the user request from the front of the abstract information, the server has been based on the information to calculate a summary, and then according to the abstract information over the comparison, and then confirm the user identity.

After the configuration is complete, restart the server for testing.

The test effect is the same as HttpBasic authentication, all the changes are just behind the implementation changes, the user experience is the same.

4. Summary

Http digest authentication is more secure than HttpBasic, but as you can see, the entire process solves very limited security problems. And the code was a lot more cumbersome, so authentication didn’t catch on.

Http authentication partners as a understanding can, there are some ideas or very interesting, can inspire us to solve other problems, such as the solution to replay attacks, if we want to defend replay attacks, we can refer to the implementation of ideas here.

Well, if you have a harvest, remember to click on the songge under the encouragement of watching oh ~