[Spring Security + OAuth2 + JWT entry to actual combat] 20. Password modification login returns standard oauth2 message

Keywords: Programming Spring Java JSON Apache

brief introduction

Before modification, password login returns standard OAuth2 login success message

Technological process

Refer to this process to generate a token in the login success processor HkAuthenticationSuccessHandler and return:

This is a successful processor copied from the previous browser project. We need to install the above flowchart on this basis to change it

package com.spring.security.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.properties.LoginType;
import com.spring.security.properties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Authentication success handler
 */
@Component("hkAuthenticationSuccessHandler")
public class HkAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Autowired
    private SecurityProperties securityProperties;
    @Autowired
    private ObjectMapper mapper;

    /**
     * Authentication succeeded
     *
     * @param request        request
     * @param response       response
     * @param authentication Identity verification
     * @throws IOException      IOException
     * @throws ServletException Servlet abnormal
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //Determine the return type of configuration
        if (LoginType.JSON.equals(securityProperties.getBrowser().getLoginType())) {
            response.setContentType("application/json;charset=utf-8");
            response.getWriter().write(mapper.writeValueAsString(authentication));
        } else {
            redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginSucess());
        }

    }
}

After transformation:

package com.spring.security.authentication;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.spring.security.properties.LoginType;
import com.spring.security.properties.SecurityProperties;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;

/**
 * Authentication success handler
 */
@Component("hkAuthenticationSuccessHandler")
public class HkAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private AuthorizationServerTokenServices authorizationServerTokenServices;


    /**
     * Authentication succeeded
     *
     * @param request        request
     * @param response       response
     * @param authentication Identity verification
     * @throws IOException      IOException
     * @throws ServletException Servlet abnormal
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        // 1. Get ClientId from request header
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Basic ")) {
            throw new UnapprovedClientAuthenticationException("None in request header client information");
        }

        String[] tokens = this.extractAndDecodeHeader(header, request);
        String clientId = tokens[0];
        String clientSecret = tokens[1];


        // 2. Get ClientDetails through ClientDetailsService
        ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);

        TokenRequest tokenRequest = null;

        // 3. Verify the correctness of ClientId and ClientSecret
        if (clientDetails == null) {
            throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "Corresponding information does not exist");
        } else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
            throw new UnapprovedClientAuthenticationException("clientSecret Incorrect");
        } else {
            // 4. Generate TokenRequest through TokenRequest constructor
            tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
        }
        // 5. Obtain OAuth2Request through the createOAuth2Request method of TokenRequest
        OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
        // 6. Construct OAuth2Authentication through Authentication and OAuth2Request
        OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);

        // 7. Generate OAuth2AccessToken through authorizationservertoken services
        OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);

        //Return message
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(new ObjectMapper().writeValueAsString(token));

    }


    private String[] extractAndDecodeHeader(String header, HttpServletRequest request) {
        //Remove the first six fixed Basic bits
        byte[] base64Token = header.substring(6).getBytes(StandardCharsets.UTF_8);

        byte[] decoded;
        try {
            decoded = Base64.getDecoder().decode(base64Token);
        } catch (IllegalArgumentException var7) {
            throw new BadCredentialsException("Failed to decode basic authentication token");
        }

        String token = new String(decoded, StandardCharsets.UTF_8);
        //Group by colon
        int delim = token.indexOf(":");
        if (delim == -1) {
            //If you don't find a colon, throw an exception
            throw new BadCredentialsException("Invalid basic authentication token");
        } else {
            return new String[]{token.substring(0, delim), token.substring(delim + 1)};
        }
    }
}

Add some basic Spring Security configurations to the resource server, copy them from the browser project, change them, delete the useless configurations first:

package com.spring.security;

import com.spring.security.authentication.HkAuthenticationFailureHandler;
import com.spring.security.authentication.HkAuthenticationSuccessHandler;
import com.spring.security.properties.SecurityConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

/**
 * Resource server
 */
@Configuration
@EnableResourceServer
public class HkResourceServerConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private HkAuthenticationSuccessHandler hkAuthenticationSuccessHandler;
    @Autowired
    private HkAuthenticationFailureHandler hkAuthenticationFailureHandler;

    @Override
    public void configure(HttpSecurity http) throws Exception {

        http.formLogin() // Form login
                .loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
                .loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)// Process form login URL
                .successHandler(hkAuthenticationSuccessHandler)// Login processed successfully
                .failureHandler(hkAuthenticationFailureHandler)// Failed to process login
                .and()
                .authorizeRequests() // Authorized configuration
                .anyRequest()  // All requests
                .authenticated() // All need certification
                .and()
                .csrf().disable();
    }
}
 /**
     * Default username password login request processing url
     */
    public static final String DEFAULT_LOGIN_PROCESSING_URL_FORM = "/authentication/form";

Start the project and use postman to send the login request http://127.0.0.1:8080/authentication/form:

Authorization: Basic plus client ﹣ ID: client ﹣ secret is base64 encrypted

Click send to get the token successfully:

Get resources:

Posted by Maknis on Wed, 18 Mar 2020 09:05:42 -0700