spring-security (22) basic authentication and digest authentication

Foreword:
  Basic authentication and digest authentication are very popular as alternative authentication mechanisms in web applications. Among them, basic authentication is often used to authenticate stateless clients. For example, in combination with the form-based authentication form, we can provide authentication to users who access through browsers and users who access through web-service (restful). Because the user name and password are sent to the server in text form during basic authentication, in applications with high security levels, basic authentication needs to be encrypted during transmission, for example, in the form of https.
1. Basic Authentication
1. Filter BasicAuthenticationFilter
The logic related to basic authentication is mainly in this filter. When the filter receives a request, it is executed according to the following logic
  • Obtain the data corresponding to the attribute Authorization from the header of the request. If the value corresponding to Authorization does not start with [Basic], it means that the authentication is not in basic form, and the current filter is skipped.
  • Obtain the data after [Basic], decode it with Base64, and divide it with [:] after decoding. The first part is the user name, and the second part is the password
  • Assemble UsernamePasswordAuthenticationToken with the username and password obtained in the previous step, and then call the authenticationManager.authenticate method for authentication
  • If the authentication is successful, put the assembled Authentication object into the SecurityContextHolder and call the rememberMeServices.loginSuccess service to encode the username and password and store it in the cookie, and execute the remember user function.
  • If the authentication fails, clear the authentication object in the SecurityContextHolder, call rememberMeServices.loginFail to clear the cookie information, call the Commence method of BasicAuthenticationEntryPoint, set the header of the response, append the WWW-Authenticate information, and set the return code to 401
  • E.g
    HTTP/1.1 401
    X-Content-Type-Options	nosniff
    X-XSS-Protection	1; mode=block
    Cache-Control	no-cache, no-store, max-age=0, must-revalidate
    Pragma	no-cache
    Expires	0
    X-Frame-Options	DENY
    Set-Cookie	JSESSIONID=493B4D42EC4A2D5AA85C7521288F54F9; Path=/; HttpOnly
    WWW-Authenticate	Basic realm="Realm"
    Content-Type	text/html;charset=ISO-8859-1
    Content-Language	zh-CN
    Content-Length	344
    Date	Tue, 06 Mar 2018 01:42:28 GMT
    Proxy-Connection	Keep-alive
    

    After the browser receives the information, a pop-up box prompts the user to enter the username and password, and then the browser encodes the username and password and sends it to the server, for example:
    GET /index.html HTTP/1.1
    Host	localhost:8080
    Cache-Control	max-age=0
    Authorization	Basic dXNlcjpwYXNzd29yZA==
    Upgrade-Insecure-Requests	1
    User-Agent	Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
    Accept	text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding	gzip, deflate, br
    Accept-Language	zh-CN,zh;q=0.9,en;q=0.8
    Cookie	JSESSIONID=493B4D42EC4A2D5AA85C7521288F54F9
    

    [dXNlcjpwYXNzd29yZA==] The corresponding value is the encrypted information of the user name and password.
    The authentication process is as follows:





    2. From the above content, we can see that the authentication logic of this authentication method is very simple, and the developer does not need to consider how the login page is displayed, and the development method is very simple. However, using this authentication method, the request header information is transmitted in clear code during the transmission process. The user name and password encryption method used is BASE-64. The decoding process is very simple. It is cracked, so its authentication technology is not very secure. Generally, it is used on embedded devices. In practical applications, it is best to combine the TLS technology to encrypt the transmitted information to improve security.
    3. It is also very simple to enable basic authentication in the spring boot application
    @Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    		.csrf()
    			.disable()
    		.authorizeRequests()
    			.anyRequest().authenticated()
    			.and()
    		.httpBasic();
    	}
    

    You can call the httpBasic() method of HttpSecurity. How to add BasicAuthenticationFilter to the servletContext for this method can be found in the previous article. The explanation of the core filter is not expanded here.

    2. Digest authentication
    1. Digest authentication is mainly to solve the problem that the password is easy to be cracked in the basic authentication, and to improve the security by encrypting the authentication information. It is best not to consider using digest authentication in enterprise-level application development. It only improves the security of basic authentication, but there are still security holes. The most obvious problem is that you have to save the password in one of clear text, encoded, MD5 processed, and these algorithms are all reversible algorithms, so they are all insecure. Instead, we should use a unidirectional hash algorithm (bCrypt, PBKDF2, SCrypt) to protect our passwords. This authentication method should be considered only when a more secure authentication method cannot be used under the constraints of some external factors. 2. The core of digest authentication is an incomprehensible character-"nonce" generated by the server, which is generated by the following algorithm




    base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
    expirationTime: The point in time at which the nonce expires, in milliseconds
    key: a private key to prevent the nonce from being modified
    

    Because the client has been encrypted when passing the user credentials to the server, and the password information cannot be recovered, so we must take the original password and go through the same hash algorithm to get the result and then compare it with the client's result, which is why we The reason why the user password must be stored in clear text .

    3. The logic related to DigestAuthenticationFilter
    and digest authentication are all in this Filter. The main processing logic is as follows:
  • Obtain the data corresponding to the attribute Authorization from the header of the request. If the value corresponding to Authorization does not start with [Digest], it means that the authentication is not in basic form, and the current filter is skipped.
  • Get the data after [Digest] and assemble it into DigestData
  • Use the key and realm corresponding to the generated nonce to verify the DigestData
  • After the verification is successful, call userDetailsService.loadUserByUsername to obtain user information
  • Compare the obtained user's password through MD5 calculation with the result passed by the client. If they are consistent, the authentication is successful.
  • After the authentication is successful, the user information is encapsulated into Authentication and stored in the SecurityContextHolder
  • If the verification in the above steps is unsuccessful, the verification is considered to have failed, and the subsequent filters are executed
  • In the subsequent filter, because there is no normal authentication, the ExceptionTranslationFilter will eventually catch the exception, call the commence method of DigestAuthenticationEntryPoint, set the response header information, and return a 401 to the client, for example
    HTTP/1.1 401
    X-Content-Type-Options	nosniff
    X-XSS-Protection	1; mode=block
    Cache-Control	no-cache, no-store, max-age=0, must-revalidate
    Pragma	no-cache
    Expires	0
    X-Frame-Options	DENY
    Set-Cookie	JSESSIONID=AE5A3F9F3ED75248B801954C58850A39; Path=/; HttpOnly
    WWW-Authenticate	Digest realm="security", qop="auth", nonce="MTUyMDMyMjk3NDIzOTpjOGZiMzYyY2MzNTQ1ZGQwN2UwNzE1YzE2YjExNWQwMg=="
    Content-Type	text/html;charset=ISO-8859-1
    Content-Language	zh-CN
    Content-Length	344
    Date	Tue, 06 Mar 2018 07:51:14 GMT
    Proxy-Connection	Keep-alive
    

    After that, the browser pop-up box prompts the user to enter the username and password, and then the browser encodes the username and password and sends it to the server
    GET /index.html HTTP/1.1
    Host	localhost:8080
    Cache-Control	max-age=0
    Authorization	Digest username="user", realm="security", nonce="MTUyMDMyMjk3NDIzOTpjOGZiMzYyY2MzNTQ1ZGQwN2UwNzE1YzE2YjExNWQwMg==", uri="/index.html", response="87007805d864a0f07f0bbf0e915fbe68", qop=auth, nc=00000001, cnonce="645f7f377909cc62"
    Upgrade-Insecure-Requests	1
    User-Agent	Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
    Accept	text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding	gzip, deflate, br
    Accept-Language	zh-CN,zh;q=0.9,en;q=0.8
    Cookie	JSESSIONID=AE5A3F9F3ED75248B801954C58850A39
    


    The authentication flow chart is the same as basic authentication, the only difference is that Filter is replaced by DigestAuthenticationFilter, and the process is no longer drawn here.

    4. Configure the degist authentication method in spring boot
    @Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    		.csrf()
    			.disable()
    		.authorizeRequests()
    			.anyRequest().authenticated()
    			.and()
    		.exceptionHandling()
    			.authenticationEntryPoint(digestEntryPoint()).and()
    		.addFilter(digestFilter());
    	}
    
    	@Bean
    	public DigestAuthenticationEntryPoint digestEntryPoint() {
    		DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
    		entryPoint.setKey("chengf");
    		entryPoint.setRealmName("security");
    		return entryPoint;
    	}
    	
    	@Bean
    	public DigestAuthenticationFilter digestFilter() throws Exception {
    		DigestAuthenticationFilter digestFilter = new DigestAuthenticationFilter();
    		digestFilter.setAuthenticationEntryPoint(digestEntryPoint());
    		digestFilter.setUserDetailsService(userDetailsService());
    		return digestFilter;
    	}
    



    Complete sample code reference: source code

    Guess you like

    Origin http://43.154.161.224:23101/article/api/json?id=326060248&siteId=291194637