Spring Security(八):认证(Authentication)-社交登录(Social)-绑定和解绑

一:绑定

当用于已经在平台上注册过账号之后,可以通过绑定将第三方社交账号绑定到平台注册的账号,以后使用第三方社交账号登录即可。

绑定和解绑的原理是在原来的第三方社交登录的基础之上增加了一个org.springframework.social.connect.web.ConnectController类,用于接收绑定和解绑的请求。

二:获取社交账号的绑定结果

MyConnectionStatusView: 连接状态视图,Spring Security Social会获取所有已配置的社交账号的绑定情况,然后调用"connect/status"这个组件,这里是以json的格式输出。

@Component("connect/status")
public class MyConnectionStatusView extends AbstractView {
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, List<Connection<?>>> connections = (Map<String, List<Connection<?>>>) model.get("connectionMap");

        Map<String, Boolean> result = new HashMap<>();
        for (String key : connections.keySet()) {
            result.put(key, !CollectionUtils.isEmpty(connections.get(key)));
        }

        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSONObject.toJSONString(result));
    }
}

ConnectController 是Spring Security Social已经写好的控制器,请求路径为@RequestMapping("/connect")

@Configuration
@EnableSocial
public class SocialConfiguration extends SocialConfigurerAdapter {
	@Bean
    public ConnectController connectController(ConnectionFactoryLocator connectionFactoryLocator, ConnectionRepository connectionRepository) {
        return new ConnectController(connectionFactoryLocator, connectionRepository);
    }
}

在这里插入图片描述

  1. 先访问登录页面 http://xxx.com/login,输入admin/123456进行登录
  2. 再访问/connect路径 http://xxx.com/connect 获取QQ和Weixin是否已经绑定过,false表示没有绑定过
    在这里插入图片描述

三:绑定

注意:在引入social相关依赖时不要用1.1.4这个版本,这个版本有严重的bug,缺少方法,这里使用最新的版本1.1.6.RELEASE

<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-web</artifactId>
    <version>1.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-core</artifactId>
    <version>1.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-config</artifactId>
    <version>1.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.social</groupId>
    <artifactId>spring-social-security</artifactId>
    <version>1.1.6.RELEASE</version>
</dependency>

binding.html
这里演示的是QQ绑定,微信绑定和QQ原理一样,只不过发送的地址对应的providerId不一样,绑定的请求的路径为/connect/providerId, QQ 的providerId设置为"callback.do", 所以整体路径为"/connect/callback.do"

<!DOCTYPE html>
<html lang="en"
      xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8">
    <title>绑定</title>
</head>
<body>

<form action="/connect/callback.do" method="post">
    <button type="submit">绑定QQ</button>
</form>

</body>
</html>
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/signup").setViewName("signup");
        registry.addViewController("/binding").setViewName("binding");
        registry.addViewController("/index").setViewName("index");
    }
}

MyConnectedView: 绑定成功的页面视图

public class MyConnectedView extends AbstractView {
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("绑定成功");
    }
}
@Configuration
@ConditionalOnProperty(prefix = "social.qq", name = "appId")
@EnableConfigurationProperties(QQProperties.class)
public class QQAutoConfig extends SocialConfigurerAdapter {
	/**
     * 关于bean的名称spring-social-web不同的版本可能不一样,具体是什么可以通过下面的类打端点看一下
     * org.springframework.social.connect.web.ConnectController#connectionStatusRedirect(java.lang.String, org.springframework.web.context.request.NativeWebRequest)
     * @return
     */
	@Bean("connect/callback.do.doConnect")
    public View qqConnectedView() {
        return new MyConnectedView();
    }
}
@Configuration
@ConditionalOnProperty(prefix = "social.weixin", name = "appId")
@EnableConfigurationProperties(WeixinProperties.class)
public class WeixinAutoConfiguration extends SocialConfigurerAdapter {
	/**
     * 关于bean的名称spring-social-web不同的版本可能不一样,具体是什么可以通过下面的类打端点看一下
     * org.springframework.social.connect.web.ConnectController#connectionStatusRedirect(java.lang.String, org.springframework.web.context.request.NativeWebRequest)
     * @return
     */
    @Bean("connect/weixin.doConnect")
    public View weixinConnectedView() {
        return new MyConnectedView();
    }
}

网站回调域
注意网站回调域不光要配置filterProcessesUrl/providerId对应的地址,也要配置connect/providerId地址,也就是说网站回调域要配置两个地址,中间都分号分割。如 http://www.example.com/qqLogin/callback.do;http://www.example.com/connect/callback.do

先访问登录页面/login,再访问绑定页面/binding

绑定成功后可以看到UserConnection表的userid变成了登录时使用的用户名
在这里插入图片描述

四:解绑

绑定和解绑使用同一个视图

public class MyConnectedView extends AbstractView {
    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        response.setContentType("text/html;charset=UTF-8");
        if (model.get("connection") == null) {
            response.getWriter().write("绑定成功");
        } else {
            response.getWriter().write("解绑成功");
        }
    }
}
@Configuration
@ConditionalOnProperty(prefix = "social.qq", name = "appId")
@EnableConfigurationProperties(QQProperties.class)
public class QQAutoConfig extends SocialConfigurerAdapter {
	/**
     * 关于bean的名称spring-social-web不同的版本可能不一样,具体是什么可以通过下面的类打端点看一下
     * org.springframework.social.connect.web.ConnectController#connectionStatusRedirect(java.lang.String, org.springframework.web.context.request.NativeWebRequest)
     * @return
     */
    @Bean({"connect/callback.do.doConnect", "connect/callback.doConnected"})
    public View qqConnectedView() {
        return new MyConnectedView();
    }
}
@Configuration
@ConditionalOnProperty(prefix = "social.weixin", name = "appId")
@EnableConfigurationProperties(WeixinProperties.class)
public class WeixinAutoConfiguration extends SocialConfigurerAdapter {
	/**
     * 关于bean的名称spring-social-web不同的版本可能不一样,具体是什么可以通过下面的类打端点看一下
     * org.springframework.social.connect.web.ConnectController#connectionStatusRedirect(java.lang.String, org.springframework.web.context.request.NativeWebRequest)
     * @return
     */
    @Bean({"connect/weixin.doConnect", "connect/weixin.doConnected"})
    public View weixinConnectedView() {
        return new MyConnectedView();
    }
}

使用Chrome插件Restlet Client发送解绑请求,请求方式为Delete
在这里插入图片描述
解绑后UserConnection表之前userid=admin的这条数据没有了
在这里插入图片描述

发布了308 篇原创文章 · 获赞 936 · 访问量 133万+

猜你喜欢

转载自blog.csdn.net/vbirdbest/article/details/91127199
今日推荐