package cn.mb.cloud.auth.security.handler; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.CharsetUtil; import cn.mb.cloud.auth.security.util.AuthUtils; import cn.mb.cloud.common.core.util.ResponseData; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Builder; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.common.exceptions.InvalidClientException; import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException; import org.springframework.security.oauth2.provider.*; import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @author jason * 手机号登录成功,返回oauth token */ @Slf4j @Builder public class MobileLoginSuccessHandler implements AuthenticationSuccessHandler { private static final String BASIC_ = "Basic "; private ObjectMapper objectMapper; private PasswordEncoder passwordEncoder; private ClientDetailsService clientDetailsService; private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices; /** * Called when a user has been successfully authenticated. * 调用spring security oauth API 生成 oAuth2AccessToken * * @param request the request which caused the successful authentication * @param response the response * @param authentication the Authentication object which was created during */ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { String header = request.getHeader(HttpHeaders.AUTHORIZATION); if (header == null || !header.startsWith(BASIC_)) { throw new UnapprovedClientAuthenticationException("请求头中client信息为空"); } try { String[] tokens = AuthUtils.extractAndDecodeHeader(header); assert tokens.length == 2; String clientId = tokens[0]; ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId); //校验secret if (!passwordEncoder.matches(tokens[1], clientDetails.getClientSecret())) { throw new InvalidClientException("Given client ID does not match authenticated client"); } TokenRequest tokenRequest = new TokenRequest(MapUtil.newHashMap(), clientId, clientDetails.getScope(), "mobile"); //校验scope new DefaultOAuth2RequestValidator().validateScope(tokenRequest, clientDetails); OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails); OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication); OAuth2AccessToken oAuth2AccessToken = defaultAuthorizationServerTokenServices.createAccessToken(oAuth2Authentication); log.info("获取token 成功:{}", oAuth2AccessToken.getValue()); response.setCharacterEncoding(CharsetUtil.UTF_8); response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE); PrintWriter printWriter = response.getWriter(); printWriter.append(objectMapper.writeValueAsString(ResponseData.success(oAuth2AccessToken))); } catch (IOException e) { throw new BadCredentialsException( "Failed to decode basic authentication token"); } } }