简介
用户登录以后读取用户第三方登录是否绑定,已绑定显示解绑按钮,未绑定显示去绑定按钮
读取用户第三方登录详细源码分析
SpringSocial已经未我们提供了方法ConnectController来读取以后第三方登录信息
在SocialConfig类把ConnectController添加到bean
// 这个是提供查询社交账户信息服务,绑定服务,等
@Bean
public ConnectController connectController(
ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
return new ConnectController(connectionFactoryLocator, connectionRepository);
}
ConnectController
org.springframework.social.connect.web.ConnectController
public String connectionStatus(NativeWebRequest request, Model model) {
this.setNoCache(request);
this.processFlash(request, model);
Map>> connections = this.connectionRepository.findAllConnections();
model.addAttribute("providerIds", this.connectionFactoryLocator.registeredProviderIds());
model.addAttribute("connectionMap", connections);
return this.connectView();
}
在connectionStatus方法打断点,启动项目访问:域名/connect
我当前登录的账号绑定了QQ没有绑定weixin,继续下一步看跳默认转到哪
默认跳转:connect/status 这个页面没有我们重写一下
ConnectionStatusView
com.spring.security.social创建ConnectionStatusView类
package com.spring.security.social;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.Connection;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 读取第三方绑定数据
*/
@Component("connect/status")
public class ConnectionStatusView extends AbstractView {
@Autowired
private ObjectMapper objectMapper;
@Override
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
//取model里封装好的信息
Map>> connections = (Map>>) model.get("connectionMap");
//返回报文 是否绑定
Map r = new HashMap<>();
//遍历connections里面数据
for (String key : connections.keySet()) {
//判断取出来的值是否为null 返回是否
r.put(key, CollectionUtils.isNotEmpty(connections.get(key)));
}
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(r));
}
}
重启项目看是否能返回报文:
绑定
绑定源码,重新走认证流程
/**
* Process a connect form submission by commencing the process of establishing a connection to the provider on behalf of the member.
* For OAuth1, fetches a new request token from the provider, temporarily stores it in the session, then redirects the member to the provider's site for authorization.
* For OAuth2, redirects the user to the provider's site for authorization.
* @param providerId the provider ID to connect to
* @param request the request
* @return a RedirectView to the provider's authorization page or to the connection status page if there is an error
*/
@RequestMapping(value="/{providerId}", method=RequestMethod.POST)
public RedirectView connect(@PathVariable String providerId, NativeWebRequest request) {
ConnectionFactory> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);
MultiValueMap parameters = new LinkedMultiValueMap();
preConnect(connectionFactory, parameters, request);
try {
return new RedirectView(connectSupport.buildOAuthUrl(connectionFactory, request, parameters));
} catch (Exception e) {
sessionStrategy.setAttribute(request, PROVIDER_ERROR_ATTRIBUTE, e);
return connectionStatusRedirect(providerId, request);
}
}
创建banding.html页面
标准绑定页面标准绑定解绑页面
绑定QQ
绑定微信
启动项目测试
使用表单登录访问页面banding.html
清空数据库表:
点击绑定QQ
如果出现这个错误请把/connect/qq加到QQ互联的回调地址:http://127.0.0.1/auth/qq;http://127.0.0.1/connect/qq
继续登录:
数据已经绑定成功,但是绑定成功以后的跳转报错,现在做一下绑定成功以后的跳转
绑定成功跳转
com.spring.security.social目录创建HkConnectView绑定成功和解绑成功跳转视图类
package com.spring.security.social;
import org.springframework.web.servlet.view.AbstractView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* 绑定成功和解绑成功跳转视图 需要放配置中管理bean
*/
public class HkConnectView extends AbstractView {
@Override
protected void renderMergedOutputModel(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
response.setContentType("text/html;charset=UTF-8");
if (model.get("connections") == null) {
response.getWriter().write("
" + model.get("providerId") + "解绑成功
");} else {
response.getWriter().write("
" + model.get("providerId") + "绑定成功
");}
}
}
注入绑定bean
QQAutoConfig类添加bean配置
/**
* QQ绑定解绑界面视图
* connect/qqConnected:绑定
* connect/qqConnect:解绑
*
* @return
*/
@Bean({"connect/qqConnect", "connect/qqConnected"})
@ConditionalOnMissingBean(name = "qqConnectedView") //可以自定义实现覆盖此默认界面
public HkConnectView qqConnectedView() {
return new HkConnectView();
}
WeixinAutoConfig类添加bean配置
/**
* weixin绑定解绑界面视图
* connect/weixinConnected:绑定
* connect/weixinConnect:解绑
*
* @return
*/
@Bean({"connect/weixinConnect", "connect/weixinConnected"})
@ConditionalOnMissingBean(name = "weixinConnectedView") //可以自定义实现覆盖此默认界面
public HkConnectView weixinConnectedView() {
return new HkConnectView();
}
启动项目测试,清空数据库表:
绑定就到此结束了。
解绑
解绑源码
/**
* Remove all provider connections for a user account.
* The user has decided they no longer wish to use the service provider from this application.
* Note: requires {@link HiddenHttpMethodFilter} to be registered with the '_method' request parameter set to 'DELETE' to convert web browser POSTs to DELETE requests.
* @param providerId the provider ID to remove the connections for
* @param request the request
* @return a RedirectView to the connection status page
*/
@RequestMapping(value="/{providerId}", method=RequestMethod.DELETE)
public RedirectView removeConnections(@PathVariable String providerId, NativeWebRequest request) {
ConnectionFactory> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);
preDisconnect(connectionFactory, request);
connectionRepository.removeConnections(providerId);
postDisconnect(connectionFactory, request);
return connectionStatusRedirect(providerId, request);
}
解绑和绑定请求地址是一样的,区别:
绑定是POST请求
解绑是DELETE请求
DELETE无法用表单发送请求只能用postman模拟实现