【SpringSecurity+OAuth2+JWT入门到实战】20.改造密码登录返回标准oauth2报文
简介
改造之前密码登录返回标准的OAuth2登录成功报文
流程
参考这个流程,来实现在登录成功处理器HkAuthenticationSuccessHandler
里生成令牌并返回:
这个是从之前browser项目拷贝过来的成功处理器,我们在这个基础安装上面的流程图去改
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;
/**
* 认证成功处理程序
*/
@Component("hkAuthenticationSuccessHandler")
public class HkAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Autowired
private SecurityProperties securityProperties;
@Autowired
private ObjectMapper mapper;
/**
* 身份验证成功
*
* @param request 请求
* @param response 响应
* @param authentication 身份验证
* @throws IOException IOException
* @throws ServletException Servlet异常
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
//判断配置的返回类型
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());
}
}
}
改造后:
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;
/**
* 认证成功处理程序
*/
@Component("hkAuthenticationSuccessHandler")
public class HkAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerTokenServices authorizationServerTokenServices;
/**
* 身份验证成功
*
* @param request 请求
* @param response 响应
* @param authentication 身份验证
* @throws IOException IOException
* @throws ServletException Servlet异常
*/
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
// 1. 从请求头中获取 ClientId
String header = request.getHeader("Authorization");
if (header == null || !header.startsWith("Basic ")) {
throw new UnapprovedClientAuthenticationException("请求头中无client信息");
}
String[] tokens = this.extractAndDecodeHeader(header, request);
String clientId = tokens[0];
String clientSecret = tokens[1];
// 2. 通过 ClientDetailsService 获取 ClientDetails
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
TokenRequest tokenRequest = null;
// 3. 校验 ClientId和 ClientSecret的正确性
if (clientDetails == null) {
throw new UnapprovedClientAuthenticationException("clientId:" + clientId + "对应的信息不存在");
} else if (!StringUtils.equals(clientDetails.getClientSecret(), clientSecret)) {
throw new UnapprovedClientAuthenticationException("clientSecret不正确");
} else {
// 4. 通过 TokenRequest构造器生成 TokenRequest
tokenRequest = new TokenRequest(new HashMap<>(), clientId, clientDetails.getScope(), "custom");
}
// 5. 通过 TokenRequest的 createOAuth2Request方法获取 OAuth2Request
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
// 6. 通过 Authentication和 OAuth2Request构造出 OAuth2Authentication
OAuth2Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
// 7. 通过 AuthorizationServerTokenServices 生成 OAuth2AccessToken
OAuth2AccessToken token = authorizationServerTokenServices.createAccessToken(auth2Authentication);
//返回报文
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(new ObjectMapper().writeValueAsString(token));
}
private String[] extractAndDecodeHeader(String header, HttpServletRequest request) {
//去掉前面6位固定 Basic
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);
//通过冒号分组
int delim = token.indexOf(":");
if (delim == -1) {
//如果没有找到冒号就抛异常
throw new BadCredentialsException("Invalid basic authentication token");
} else {
return new String[]{token.substring(0, delim), token.substring(delim + 1)};
}
}
}
在资源服务器上加入一些基本的Spring Security配置,从browser项目拷贝过来改吧改吧先删除无用配置:
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;
/**
* 资源服务器
*/
@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() // 表单登录
.loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
.loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)// 处理表单登录 URL
.successHandler(hkAuthenticationSuccessHandler)// 处理登录成功
.failureHandler(hkAuthenticationFailureHandler)// 处理登录失败
.and()
.authorizeRequests() // 授权配置
.anyRequest() // 所有请求
.authenticated() // 都需要认证
.and()
.csrf().disable();
}
}
/** * 默认的用户名密码登录请求处理url
*/
public static final String DEFAULT_LOGIN_PROCESSING_URL_FORM = "/authentication/form";
启动项目,使用postman发送登录请求http://127.0.0.1:8080/authentication/form:
Authorization:Basic
加上client_id:client_secret
经过base64加密
点击发送后便可以成功获取到令牌:
获取资源:
以上是 【SpringSecurity+OAuth2+JWT入门到实战】20.改造密码登录返回标准oauth2报文 的全部内容, 来源链接: utcz.com/z/514504.html