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: