【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

回到顶部