【SpringSecurity+OAuth2+JWT入门到实战】23.改造基于APP接口社交注册

编程

简介

上章完成社交登录但是我们是在数据库有用户的情况下登录了,这章解决数据库无该用户数据先完成注册再登录。

流程

看之前浏览器代码如果用户未注册我们会把用户引导到注册页面

注册完成以后访问/social/user连接通过ProviderSignInUtils帮助包到session取用户资料

登录通过以会拿到用户的唯一标识再调用doPostSignUp方法从session拿出用户资料进行绑定再添加到数据库

到这里我们也看到问题那就是整个流程都是基于session完成的,但是我们APP是无session的

改造

改造思路如果第三方信息在数据库查不到数据先保存到Redis等用户注册完我们平台账号拿到userId以后再绑定保存到数据库

创建帮助类AppSingUpUtils:

/**

*

*/

package com.spring.security.social;

import java.util.concurrent.TimeUnit;

import com.spring.security.AppSecretException;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.social.connect.Connection;

import org.springframework.social.connect.ConnectionData;

import org.springframework.social.connect.ConnectionFactoryLocator;

import org.springframework.social.connect.UsersConnectionRepository;

import org.springframework.stereotype.Component;

import org.springframework.web.context.request.WebRequest;

/**

* app环境下替换providerSignInUtils,避免由于没有session导致读不到社交用户信息的问题

*

*/

@Component

public class AppSingUpUtils {

@Autowired

private RedisTemplate<Object, Object> redisTemplate;

@Autowired

private UsersConnectionRepository usersConnectionRepository;

@Autowired

private ConnectionFactoryLocator connectionFactoryLocator;

/**

* 缓存社交网站用户信息到redis

* @param request

* @param connectionData

*/

public void saveConnectionData(WebRequest request, ConnectionData connectionData) {

redisTemplate.opsForValue().set(getKey(request), connectionData, 10, TimeUnit.MINUTES);

}

/**

* 将缓存的社交网站用户信息与系统注册用户信息绑定

* @param request

* @param userId

*/

public void doPostSignUp(WebRequest request, String userId) {

String key = getKey(request);

if(!redisTemplate.hasKey(key)){

throw new AppSecretException("无法找到缓存的用户社交账号信息");

}

ConnectionData connectionData = (ConnectionData) redisTemplate.opsForValue().get(key);

Connection<?> connection = connectionFactoryLocator.getConnectionFactory(connectionData.getProviderId())

.createConnection(connectionData);

usersConnectionRepository.createConnectionRepository(userId).addConnection(connection);

redisTemplate.delete(key);

}

/**

* 获取redis key

* @param request

* @return

*/

private String getKey(WebRequest request) {

String deviceId = request.getHeader("deviceId");

if (StringUtils.isBlank(deviceId)) {

throw new AppSecretException("设备id参数不能为空");

}

return "imooc:security:social.connect." + deviceId;

}

}

 异常处理

/**

*

*/

package com.spring.security;

public class AppSecretException extends RuntimeException {

/**

*

*/

private static final long serialVersionUID = -1629364510827838114L;

public AppSecretException(String msg){

super(msg);

}

}

 提取hkSocialSecurityConfig类:

package com.spring.security.social;

import com.spring.security.properties.SecurityConstants;

import com.spring.security.social.support.HkSpringSocialConfigurer;

import org.apache.commons.lang.StringUtils;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanPostProcessor;

import org.springframework.stereotype.Component;

@Component

public class SpringSocialConfigurerPostProcessor implements BeanPostProcessor {

/* (non-Javadoc)

* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

return bean;

}

/* (non-Javadoc)

* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

if(StringUtils.equals(beanName, "hkSocialSecurityConfig")){

HkSpringSocialConfigurer config = (HkSpringSocialConfigurer)bean;

config.signupUrl(SecurityConstants.DEFAULT_SOCIAL_USER_INFO_URL);

return config;

}

return bean;

}

}

/**

* 获取第三方用户信息的url

*/

String DEFAULT_SOCIAL_USER_INFO_URL = "/social/user";

创建访问/social/user控制层:

/**

*

*/

package com.spring.security;

import javax.servlet.http.HttpServletRequest;

import com.spring.security.properties.SecurityConstants;

import com.spring.security.social.AppSingUpUtils;

import com.spring.security.social.support.SocialUserInfo;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.http.HttpStatus;

import org.springframework.social.connect.Connection;

import org.springframework.social.connect.web.ProviderSignInUtils;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.ResponseStatus;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.context.request.ServletWebRequest;

@RestController

public class AppSecurityController {

@Autowired

private ProviderSignInUtils providerSignInUtils;

@Autowired

private AppSingUpUtils appSingUpUtils;

/**

* 需要注册时跳到这里,返回401和用户信息给前端

* @param request

* @return

*/

@GetMapping(SecurityConstants.DEFAULT_SOCIAL_USER_INFO_URL)

@ResponseStatus(HttpStatus.UNAUTHORIZED)

public SocialUserInfo getSocialUserInfo(HttpServletRequest request) {

SocialUserInfo socialUsrInfo = new SocialUserInfo();

Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));

socialUsrInfo.setProviderId(connection.getKey().getProviderId());

socialUsrInfo.setProviderUserId(connection.getKey().getProviderUserId());

socialUsrInfo.setNickname(connection.getDisplayName());

socialUsrInfo.setHeadimg(connection.getImageUrl());

appSingUpUtils.saveConnectionData(new ServletWebRequest(request), connection.createData());

return socialUsrInfo;

}

}

package com.spring.security.social.support;

public class SocialUserInfo {

private String providerId;

private String providerUserId;

private String nickname;

private String headimg;

public String getProviderId() {

return providerId;

}

public void setProviderId(String providerId) {

this.providerId = providerId;

}

public String getProviderUserId() {

return providerUserId;

}

public void setProviderUserId(String providerUserId) {

this.providerUserId = providerUserId;

}

public String getNickname() {

return nickname;

}

public void setNickname(String nickname) {

this.nickname = nickname;

}

public String getHeadimg() {

return headimg;

}

public void setHeadimg(String headimg) {

this.headimg = headimg;

}

}

修改用户绑定方法:

    /**

* 注册和绑定

*

* @return

*/

@PostMapping("/user/regist")

public void regist(User user, HttpServletRequest request) {

//这里不管是绑定还是添加 我们都会通过查询或者添加返回用户ID 唯一标

//我先用用户名当成唯一标识

String userId = user.getUsername();

appSingUpUtils.doPostSignUp(new ServletWebRequest(request), userId);

}

/user/regist和/social/user需要加到不需要认证配置。

启动项目通过昨天方法拿到:

http://127.0.0.1/auth/qq?code=EC04D3F128C9C0B4926384DAAC1A5DCD&state=8883f264-8eae-4c18-a0fb-9de0c61cbcc9

返回401需要APP用到用户去注册我们平台。

通过/user/regist来绑定用户账号:

点Send返回200,看数据库:

现在通过社交openId和providerId去拿token:

访问数据:

 

以上是 【SpringSecurity+OAuth2+JWT入门到实战】23.改造基于APP接口社交注册 的全部内容, 来源链接: utcz.com/z/514577.html

回到顶部