【转载】spring-security-oauth2(十四 ) 社交账号绑定与解绑

要实现绑定与解绑,首先我们需要知道社交账号的绑定状态,绑定就是重新走一下OAuth2流程,关联当前登录用户(将系统用户和社交账户绑定),解绑就是删除UserConnection表数据。Spring Social默认在ConnectController类上已经帮我们实现了以上的需求。

获取绑定状态

只有数据没有视图这个要我们根据需求来实现

org.springframework.social.connect.web.ConnectController#connectionStatus


 
 
  1. /**
  2. * Render the status of connections across all providers to the user as HTML in their web browser.
  3. * @param request the request
  4. * @param model the model
  5. * @return the view name of the connection status page for all providers
  6. */
  7. @RequestMapping(method=RequestMethod.GET)
  8. public String connectionStatus(NativeWebRequest request, Model model) {
  9. setNoCache(request);
  10. processFlash(request, model);
  11. Map<String, List<Connection<?>>> connections = connectionRepository.findAllConnections();
  12. model.addAttribute( "providerIds", connectionFactoryLocator.registeredProviderIds());
  13. model.addAttribute( "connectionMap", connections);
  14. return connectView();
  15. }
  16. //返回视图
  17. protected String connectView() {
  18. return getViewPath() + "status"; //connect/status
  19. }

实现我们的视图展示


 
 
  1. package com.rui.tiger.auth.core.social;
  2. import com.alibaba.fastjson.JSON;
  3. import org.apache.commons.collections.CollectionUtils;
  4. import org.springframework.social.connect.Connection;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.servlet.view.AbstractView;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. /**
  13. * 社交账号绑定视图
  14. * @author CaiRui
  15. * @Date 2019-01-20 10:01
  16. */
  17. @Component( "connect/status")
  18. public class TigerConnectionStatusView extends AbstractView {
  19. @Override
  20. protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
  21. Map<String, List<Connection<?>>> connections = (Map<String, List<Connection<?>>>) model.get( "connectionMap");
  22. //key :社交供应商id value:是否绑定
  23. Map<String,Boolean> bindResult= new HashMap<>();
  24. for(String providerId:connections.keySet()){
  25. bindResult.put(providerId, CollectionUtils.isNotEmpty(connections.get(providerId)));
  26. }
  27. response.setContentType( "application/json;charset=UTF-8");
  28. response.getWriter().write(JSON.toJSONString(bindResult)); //返回json
  29. }
  30. }

绑定

源码如下:


 
 
  1. /**
  2. * Process a connect form submission by commencing the process of establishing a connection to the provider on behalf of the member.
  3. * 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.
  4. * For OAuth2, redirects the user to the provider's site for authorization.
  5. * @param providerId the provider ID to connect to
  6. * @param request the request
  7. * @return a RedirectView to the provider's authorization page or to the connection status page if there is an error
  8. */
  9. @RequestMapping(value= "/{providerId}", method=RequestMethod.POST)
  10. public RedirectView connect(@PathVariable String providerId, NativeWebRequest request) {
  11. ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);
  12. MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
  13. preConnect(connectionFactory, parameters, request);
  14. try {
  15. return new RedirectView(connectSupport.buildOAuthUrl(connectionFactory, request, parameters));
  16. } catch (Exception e) {
  17. sessionStrategy.setAttribute(request, PROVIDER_ERROR_ATTRIBUTE, e);
  18. return connectionStatusRedirect(providerId, request);
  19. }
  20. }

绑定/解绑公用视图


 
 
  1. package com.rui.tiger.auth.core.social;
  2. import org.springframework.web.servlet.view.AbstractView;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletResponse;
  5. import java.util.Map;
  6. /**
  7. * 微信wechat社交账号绑定、解绑 成功返回界面 放在配置中管理bean
  8. * getViewPath() + providerId + "Connected";// connect/wechat/Connected
  9. * @author CaiRui
  10. * @Date 2019-01-20 11:19
  11. */
  12. public class TigerConnectView extends AbstractView {
  13. @Override
  14. protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
  15. response.setContentType( "text/html;charset=UTF-8");
  16. if (model.get( "connections") == null) {
  17. response.getWriter().write( "<h3>解绑成功</h3>");
  18. } else {
  19. response.getWriter().write( "<h3>绑定成功</h3>");
  20. }
  21. }
  22. }

注入绑定结果视图:


 
 
  1. package com.rui.tiger.auth.core.social.wechat.config;
  2. import com.rui.tiger.auth.core.properties.SecurityProperties;
  3. import com.rui.tiger.auth.core.properties.WechatProperties;
  4. import com.rui.tiger.auth.core.social.TigerConnectView;
  5. import com.rui.tiger.auth.core.social.wechat.connect.WechatConnectionFactory;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  8. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  9. import org.springframework.context.annotation.Bean;
  10. import org.springframework.context.annotation.Configuration;
  11. import org.springframework.core.env.Environment;
  12. import org.springframework.social.config.annotation.ConnectionFactoryConfigurer;
  13. import org.springframework.social.config.annotation.SocialConfigurerAdapter;
  14. import org.springframework.social.connect.ConnectionFactory;
  15. import org.springframework.social.connect.ConnectionFactoryLocator;
  16. import org.springframework.social.connect.UsersConnectionRepository;
  17. import org.springframework.web.servlet.View;
  18. /**
  19. * 微信登陆配置
  20. * @author CaiRui extends SocialConfigurerAdapter
  21. * @Date 2019-01-12 13:57
  22. */
  23. @Configuration
  24. @ConditionalOnProperty(prefix = "tiger.auth.social.wechat", name = "app-id")
  25. public class WechatAutoConfiguration extends SocialConfigurerAdapter {
  26. @Autowired
  27. private SecurityProperties securityProperties;
  28. @Override
  29. public void addConnectionFactories(ConnectionFactoryConfigurer connectionFactoryConfigurer, Environment environment) {
  30. connectionFactoryConfigurer.addConnectionFactory(createConnectionFactory());
  31. }
  32. private ConnectionFactory<?> createConnectionFactory() {
  33. WechatProperties weixinConfig = securityProperties.getSocial().getWechat();
  34. return new WechatConnectionFactory(weixinConfig.getProviderId(), weixinConfig.getAppId(),
  35. weixinConfig.getAppSecret());
  36. }
  37. /**
  38. * 微信绑定解绑界面视图
  39. * connect/wechatConnected:绑定
  40. * connect/wechatConnect:解绑
  41. * @return
  42. */
  43. @Bean({ "connect/wechatConnect", "connect/wechatConnected"})
  44. @ConditionalOnMissingBean(name = "wechatConnectedView") //可以自定义实现覆盖此默认界面
  45. public View wechatConnectedView(){
  46. return new TigerConnectView();
  47. }
  48. // 后补:做到处理注册逻辑的时候发现的一个bug:登录完成后,数据库没有数据,但是再次登录却不用注册了
  49. // 就怀疑是否是在内存中存储了。结果果然发现这里父类的内存ConnectionRepository覆盖了SocialConfig中配置的jdbcConnectionRepository
  50. // 这里需要返回null,否则会返回内存的 ConnectionRepository
  51. @Override
  52. public UsersConnectionRepository getUsersConnectionRepository(ConnectionFactoryLocator connectionFactoryLocator) {
  53. return null;
  54. }
  55. }

标准绑定界面:tiger-auth\tiger-auth-browser\src\main\resources\static\tiger-binding.html


 
 
  1. <html>
  2. <head>
  3. <meta charset="UTF-8">
  4. <title>绑定 </title>
  5. </head>
  6. <body>
  7. <h2>微信标准绑定页面 </h2>
  8. <form action="/connect/wechat" method="post">
  9. <button type="submit">绑定微信 </button>
  10. </form>
  11. <h2>QQ标准绑定页面 </h2>
  12. <form action="/connect/qq" method="post">
  13. <button type="submit">绑定QQ </button>
  14. </form>
  15. </body>
  16. </html>

调试:

调试qq绑定报下面错误

qq获取授权码文档:http://wiki.connect.qq.com/%e4%bd%bf%e7%94%a8authorization_code%e8%8e%b7%e5%8f%96access_token

经过源码分析发现回调地址:

https://graph.qq.com/oauth2.0/authorize?client_id=101316278&response_type=code&redirect_uri=http%3A%2F%2Fmrcode.cn%2Fconnect%2Fqq&state=8596e119-5c2a-4f2a-99cc-ec1c8a8aac85

推测要在互联回调地址也要加 /connect/qq 才可以  等待验证。

解绑

源码如下:


 
 
  1. /**
  2. * Remove all provider connections for a user account.
  3. * The user has decided they no longer wish to use the service provider from this application.
  4. * Note: requires {@link HiddenHttpMethodFilter} to be registered with the '_method' request parameter set to 'DELETE' to convert web browser POSTs to DELETE requests.
  5. * @param providerId the provider ID to remove the connections for
  6. * @param request the request
  7. * @return a RedirectView to the connection status page
  8. */
  9. @RequestMapping(value= "/{providerId}", method=RequestMethod.DELETE)
  10. public RedirectView removeConnections(@PathVariable String providerId, NativeWebRequest request) {
  11. ConnectionFactory<?> connectionFactory = connectionFactoryLocator.getConnectionFactory(providerId);
  12. preDisconnect(connectionFactory, request);
  13. connectionRepository.removeConnections(providerId);
  14. postDisconnect(connectionFactory, request);
  15. return connectionStatusRedirect(providerId, request);
  16. }

可以调用postman模拟实现    http://mrcode.cn/connect/qq

文章转载至:https://blog.csdn.net/ahcr1026212/article/details/86550205

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值