前面做的重构的操作,前提都是数据库中已经有了社交账号的信息,那么没有账号信息怎么办。之前基于浏览器时时将畲江账号信息存放在session中的,然后执行注册登录时将社交账号的信息和注册信息绑定插入数据库中。
这里我们自己写存放社交账号信息的工具类:
@Component
public class AppSingUpUtils {
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private UsersConnectionRepository usersConnectionRepository;
@Autowired
private ConnectionFactoryLocator connectionFactoryLocator;
public void saveConnectionData(WebRequest request, ConnectionData connectionData) {
redisTemplate.opsForValue().set(getKey(request), connectionData, 10, TimeUnit.MINUTES);
}
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);
}
private String getKey(WebRequest request) {
String deviceId = request.getHeader("deviceId");
if (StringUtils.isBlank(deviceId)) {
throw new AppSecretException("设备id参数不能为空");
}
return "imooc:security:social.connect." + deviceId;
}
}
然后创建SpringSocialConfigurerPostProcessor ,在所有的Bean初始化之前,如果是配置了imoocSocialSecurityConfig,就重行定义注册的处理器(不走之前的跳转注册页面的逻辑)
/**
* Bean
* 初始化之前和初始化后都要经过这个
* 需要用户注册时不要跳转到之前浏览器情况下注册页面
* 这里配置是将跳转到/social/signUp的服务上面
*
* @author zhailiang
*
*/
@Component
public class SpringSocialConfigurerPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (StringUtils.equals(beanName, "imoocSocialSecurityConfig")) {
ImoocSpringSocialConfigurer configurer = (ImoocSpringSocialConfigurer)bean;
configurer.signupUrl("/social/signUp");
return configurer;
}
return bean;
}
}
处理注册的处理器:
/**
* 将社交账号的信息封装到UserInfo里面
* @author zhailiang
*
*/
@RestController
public class AppSecurityController {
@Autowired
private ProviderSignInUtils providerSignInUtils;
@Autowired
private AppSingUpUtils appSingUpUtils;
@GetMapping("/social/signUp")
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public SocialUserInfo getSocialUserInfo(HttpServletRequest request) {
SocialUserInfo userInfo = new SocialUserInfo();
Connection<?> connection = providerSignInUtils.getConnectionFromSession(new ServletWebRequest(request));
userInfo.setProviderId(connection.getKey().getProviderId());
userInfo.setProviderUserId(connection.getKey().getProviderUserId());
userInfo.setNickname(connection.getDisplayName());
userInfo.setHeadimg(connection.getImageUrl());
appSingUpUtils.saveConnectionData(new ServletWebRequest(request), connection.createData());
return userInfo;
}
}
public class UserController {
@Autowired
private AppSingUpUtils appSingUpUtils;
@GetMapping("me")
public Object getUser(@AuthenticationPrincipal UserDetails user){
return user;
//return SecurityContextHolder.getContext().getAuthentication();
}
@PostMapping("/regist")
public void regist(User user, HttpServletRequest request) {
//不管是注册用户还是绑定用户,都会拿到一个用户唯一标识。
String userId = user.getUsername();
appSingUpUtils.doPostSignUp(new ServletWebRequest(request),userId);
}
这样如果在使用社交行号登录时,如果没有数据库没有数据信息,就会引导进行注册,而且不是走之前配置的注册页面的逻辑。
此时用户信息已经封装在UserInfo中,并存放在redis中了,在执行注册的请求,
观察数据可以发现数据库中添加了一条数据。
说明:本系列博客是记录慕课网中的教程的学习,以便我自己复习回忆。文中涉及的一些细节问题请参考慕课网中相关视频。
贴出慕课网视频教程地址: http://coding.imooc.com/class/134.html