Skip to content

基于 Spring Security 5 的无状态后端服务的安全框架,引入相应模块可支持QQ等第三方登录。基于 jarvis-security-social 模块,可快速开发自定义的第三方 OAuth2.0 登录模块。

License

Notifications You must be signed in to change notification settings

benfromchina/jarvis-security

Repository files navigation

目录

介绍

简介

jarvis-security是一个基于Spring Security 5无状态后端服务安全框架,引入相应模块可支持QQ支付宝开源中国等第三方登录。基于jarvis-security-social模块,可快速开发自定义的第三方OAuth2.0协议标准或非标准实现的登录模块。

背景

  1. 之前很精致的社交登录框架Spring Social停止维护,见Spring Social停止维护声明
  2. Spring Security 5作为替代方案,实现了标准OAuth2.0协议。但是,国内主流的第三方登录服务提供商如QQ支付宝等出于安全加密或其他未知的原因都不是那么标准(以下简称不标准),所以没法直接用;
  3. 公司正好有个刚上码的项目需要用,不妨写一个。

架构

jarvis-security                      // 父模块,统一维护依赖版本、公共配置属性、maven 插件配置等,供其他模块引用和继承
├── jarvis-security-core             // 核心包,底层的安全配置
├── jarvis-security-social           // OAuth2.0第三方登录核心模块,基于该模块可开发自己的第三方登录
├── jarvis-security-social-alipay    // 支付宝登录,基于jarvis-security-social模块
├── jarvis-security-social-oschina   // 开源中国登录,基于jarvis-security-social模块
└── jarvis-security-social-qq        // QQ登录,基于jarvis-security-social模块

功能

HttpSecurityConfigurer 替换 WebSecurityConfigurerAdapter 配置 HttpSecurity

  1. 继承 WebSecurityConfigurerAdapter 接口配置 HttpSecurity 的方式将失效!!!

  2. 实现 HttpSecurityConfigurer 接口来配置 HttpSecurity

配置不需要认证授权的请求

  1. 配置文件方式
spring:
  security:
    authorize-requests:
      permit-all:
      - http-method: GET
        path: /actuator/health,/actuator/hystrix.stream
  1. 实现AuthorizeRequestsPermitAllProvider接口
@Component
public class AuthorizeRequestsPermitAll implements AuthorizeRequestsPermitAllProvider {

	@Override
	public List<Request> getRequests() {
		List<Request> requests = new ArrayList<>();
		// 指定请求方式
		requests.add(new Request("GET", "/actuator/health"));
		// 所有请求方式
		requests.add(new Request("/actuator/hystrix.stream"));
		return requests;
	}

}

OAuth2.0第三方登录

QQ

  1. 引入依赖
<dependency>
    <groupId>io.github.benfromchina</groupId>
    <artifactId>jarvis-security-social-qq</artifactId>
    <version>1.0.1</version>
</dependency>
  1. 配置参数
spring:
  security:
    oauth2:
      client:
        registration:
          qq:
            client-id: xxxxxxxxx
            client-secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            redirect-uri: http://localhost/login/oauth2/code/qq

支付宝

  1. 引入依赖
<dependency>
    <groupId>io.github.benfromchina</groupId>
    <artifactId>jarvis-security-social-alipay</artifactId>
    <version>1.0.1</version>
</dependency>
  1. 配置参数
spring:
  security:
    oauth2:
      client:
        registration:
          alipay:
            client-id: xxxxxxxxxxxxxxxx
            redirect-uri: http://localhost/login/oauth2/code/alipay
            # 私钥文件路径,支持 classpath 或磁盘绝对路径,可选配置(实现PrivateKeySupplier接口)
            private-key-path: classpath:alipay/应用私钥2048.txt
            # 支付宝公钥文件路径,支持 classpath 或磁盘绝对路径,可选配置(实现AlipayPublicKeySupplier接口)
            alipay-public-key-path: classpath:alipay/支付宝公钥2048.txt
  1. 自定义获取私钥接口

实现 PrivateKeySupplier 接口

  1. 自定义获取支付宝公钥接口

实现 AlipayPublicKeySupplier 接口

开源中国

  1. 引入依赖
<dependency>
    <groupId>io.github.benfromchina</groupId>
    <artifactId>jarvis-security-social-oschina</artifactId>
    <version>1.0.1</version>
</dependency>
  1. 配置参数
spring:
  security:
    oauth2:
      client:
        registration:
          oschina:
            client-id: xxxxxxxxxxxxxxxxxxxx
            client-secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
            redirect-uri: http://localhost/login/oauth2/code/oschina

基于jarvis-security-social快速开发第三方登录

OAuth2.0流程图

注:以下接口描述中的数字与图中对应。

必选的接口

客户端注册构造器

实现 ClientRegistrationBuilderProvider

参考 OschinaClientRegistrationBuilderProvider

封装用户信息对象

实现 OAuth2UserConverterProvider

参考 QQUserConverterProvider

可选的接口

1步骤中获取授权码请求参数自定义

实现 OAuth2AuthorizationRequestEnhancerProvider 接口

参考 AlipayAuthorizationRequestEnhancerProvider

4.1步骤中返回的授权码参数名不叫code

实现 OAuth2AuthorizationCodeParameterNameProvider 接口

参考AlipayAuthorizationCodeParameterNameProvider

5步骤中获取令牌请求参数自定义

实现 OAuth2AuthorizationCodeGrantRequestEntityConverterProvider 接口

参考QQAuthorizationCodeGrantRequestConverterProvider

6步骤中获取令牌响应参数处理

实现 OAuth2AccessTokenResponseConverterProvider 接口

@Component
public class AkanAccessTokenResponseConverterProvider implements OAuth2AccessTokenResponseConverterProvider {

	@Override
	public boolean supports(ClientRegistration clientRegistration) {
		return Constants.REGISTRATION_ID.equalsIgnoreCase(clientRegistration.getRegistrationId());
	}

	@Override
	public OAuth2AccessTokenResponse convert(ClientRegistration clientRegistration, Map<String, String> tokenResponseParameters) {
		try {
			tokenResponseParameters = AkanUtils.getData(tokenResponseParameters, clientRegistration.getClientSecret());
		} catch (Exception e) {
			throw new HttpMessageConversionException(e.getMessage(), e);
		}
		return convert(tokenResponseParameters);
	}

}
56获取令牌过程自定义

实现 OAuth2AccessTokenResponseClientProvider 接口

参考 AlipayAccessTokenResponseClientProvider

6.1步骤中获取用户信息请求参数自定义

实现 OAuth2UserRequestEntityConverterProvider 接口

参考 QQUserRequestEntityConverterProvider

7步骤中获取用户信息响应参数处理

实现 OAuth2UserInfoResponseHttpMessageConverterProvider 接口

参考 QQUserInfoResponseHttpMessageConverterProvider

6.17获取用户信息过程自定义

实现 OAuth2UserInfoResponseClientProvider 接口

参考 AlipayUserInfoResponseClientProvider

持久化用户第三方登录信息

实现 UserConnectionRepository 接口

@Service
public class UserConnectionServiceImpl implements UserConnectionRepository {
	
	@Autowired
	private UserService userService;

	@Override
	public UserConnectionForm saveForm(UserConnectionForm form) {
		OAuth2UserDetails formUser = form.getUser();
		UserConnection formUserConnection = form.getUserConnection();
		
		UserDetailsImpl user = new UserDetailsImpl();
		BeanUtils.copyProperties(formUser, user);
		UserConnectionImpl userConnection = new UserConnectionImpl();
		BeanUtils.copyProperties(formUserConnection, userConnection);
		if (userConnection.getUserId() == null) {
			userConnection.setUserId(0l);
		}
		
		com.eastsoft.esstock.core.form.manager.UserConnectionForm savedForm = userService.saveUserConnection(new com.eastsoft.esstock.core.form.manager.UserConnectionForm(user, userConnection));
		
		user = new UserDetailsImpl();
		BeanUtils.copyProperties(savedForm.getUser(), user);
		userConnection = new UserConnectionImpl();
		BeanUtils.copyProperties(savedForm.getUserConnection(), userConnection);
		return new UserConnectionForm(user, userConnection);
	}

}

About

基于 Spring Security 5 的无状态后端服务的安全框架,引入相应模块可支持QQ等第三方登录。基于 jarvis-security-social 模块,可快速开发自定义的第三方 OAuth2.0 登录模块。

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages