接受 facebook 登录到我的 REST API

Posted

技术标签:

【中文标题】接受 facebook 登录到我的 REST API【英文标题】:Accept facebook login into my REST API 【发布时间】:2015-02-28 23:16:52 【问题描述】:

我有一个后端服务器(Java / Spring / Spring Security)。 目前,当来自移动应用程序的用户登录时,他们只需提交他们的用户名/密码,Spring Security 就会创建一个 Session 并将其分配给带有 JSESSIONID 的请求。

我们现在还将在移动应用程序“使用 Facebook 登录”上添加一个按钮。这是我对其工作原理的理解。

    移动应用使用 facebook SDK 获取“access_token” 移动应用从 facebook 检索用户资料(姓名、姓氏、电子邮件等) 移动检查(针对我的服务器)用户名是否唯一 如果用户名唯一,请调用 MY REST api,使用类似 /login/facebook POST over SSL 并传递 access_token、电子邮件、用户名等...)

    我的服务器然后检查 access_token 是否有效

    GET graph.facebook.com/debug_token? input_token=token-to-inspect &access_token=app-token-or-admin-token

    如果是,如果 facebook 返回的 UID 已经存在于我的本地数据库中,我按如下方式登录用户:
SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(username, null, ROLE_USER));

    如果我没有找到 UID,我只需创建一个新用户并登录该用户。

    从现在开始,移动设备向服务器发出的每个请求都将具有 SESSION(由 spring security 创建和附加),并且移动应用程序已通过身份验证

有人能告诉我这是否是一种好方法吗? 我应该停止使用会话并切换到 Spring-Security-OAUTH2 吗?


编辑 1

根据 Dave 的建议,这里是更新的 spring-security 配置:

    <!- handle login by providing a token-->
    <security:http pattern="/login/facebook" auto-config="false" use-expressions="true" entry-point-ref="loginUrlAuthenticationEntryPoint">
                <security:custom-filter ref="facebookLoginFilter" position="FORM_LOGIN_FILTER"/>
                <security:intercept-url pattern="/**" access="isAuthenticated()" />
    </security:http>


    <bean id="loginUrlAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <constructor-arg value="/login/facebook"></constructor-arg>
    </bean>

    <!-- handle basic username + password logins-->
    <security:http auto-config="true" use-expressions="true" entry-point-ref="forbiddenEntryPoint">
                <security:form-login login-processing-url="/security_check" authentication-failure-handler-ref="authFailureHandler"
                                     default-target-url="/" always-use-default-target="true" authentication-success-handler-ref="authSuccessHandler" />
                ...
                my others patterns..
                ...

        </security:http>
<bean id="forbiddenEntryPoint"
                class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

            <bean id="authSuccessHandler" class="my.package.AuthenticationSuccessHandlerImpl"/>
            <bean id="authFailureHandler" class="my.package.AuthenticationFailureHandlerImpl"/>

            <bean id="facebookLoginFilter" class="pl.jcommerce.ocean.web.ws.controller.FacebookLoginFilter">
                <property name="requiresAuthenticationRequestMatcher" ref="loginRequestUrlHandler"></property>
                <property name="authenticationManager" ref="authManager"></property>
            </bean>

            <security:authentication-manager id="authManager">
                <security:authentication-provider ref="facebookAuthenticationProvider" />
            </security:authentication-manager>

            <security:authentication-manager>
                <security:authentication-provider ref="webServiceUserAuthenticationProvider" />
            </security:authentication-manager>

            <bean id="loginRequestUrlHandler" class="org.springframework.security.web.util.matcher.RegexRequestMatcher">
                <constructor-arg index="0" value="/login/facebook" />
                <constructor-arg index="1" value="POST" />
                <constructor-arg index="2" value="false" />
            </bean>

【问题讨论】:

为此目的实现了一个 Spring 过滤器。请参阅以下链接:“Spring Authentication Filter for Stateless REST Endpoints which use Facebook Token for authentication”github.com/ozgengunay/FBSpringSocialRESTAuth 【参考方案1】:

Facebook 已经在使用 OAuth2 服务器端,并为客户端提供了自己的本机 SDK,因此我认为您在服务器中使用 OAuth2 没有任何优势,除非您的用例超出了您上面概述的范围. Spring OAuth2 也有客户端支持,但在本机应用程序中没有,所以我在原则上并没有看到你的提议有任何问题。您没有详细说明将在服务器中设置安全上下文的位置,我认为这可能是一个重要的细节——它必须发生在安全过滤器链中正确的位置才能使会话成为更新了。

【讨论】:

感谢您的回复!我认为使用 Oauth2 会更容易集成 facebook 登录。只是一个想法,我有机会从基于会话的迁移到令牌。关于我将在哪里对用户进行身份验证,这是我真的不知道该放在哪里的东西。你能否更详细地指出它在过滤器中的位置?跨度> 如果我是你,我会查看 UsernamePasswordAuthenticationFilter 的实现并对其进行调整以处理不同的凭据(fb 令牌而不是用户名/密码)。然后,您可以使用addFilterAfter 在与UsernamePasswordAuthenticationFilter 相同的位置添加过滤器。 完美谢谢!这就是我所做的:创建一个扩展 UsernamePasswordAuthenticationFilter 的类并覆盖“attemptAuthentication”方法。我做了一些基本检查并创建了一个以令牌为主体的身份验证对象。然后我在我的配置中创建了这个bean,并将它传递给一个新的authenticationProvider(如果一切顺利,我将通过联系facebook图形工具来处理令牌验证我对用户进行身份验证)。最后,我在我的配置中创建了一个新的“ 听起来不错(除了 XML 位,但那是你的葬礼)。 为此目的实现了一个 Spring 过滤器。请参阅以下链接:“Spring Authentication Filter for Stateless REST Endpoints which use Facebook Token for authentication”github.com/ozgengunay/FBSpringSocialRESTAuth【参考方案2】:

我根据 Dave Syer 在此处的回答以及他整理的 Spring Security Angular 材料尝试了实现类似的东西。要查看示例,请参阅我的 forked github 存储库,特别是 security 包中的类。

【讨论】:

以上是关于接受 facebook 登录到我的 REST API的主要内容,如果未能解决你的问题,请参考以下文章

Facebook:当我返回我的应用程序时,登录和权限屏幕不会关闭

使用 facebook 登录并使用 oauth 2.0 对 REST api 调用进行身份验证

如何将特定登录的公共 Facebook 页面数据(应用程序)获取到我的 android 应用程序中?

如何避免要求用户一次又一次地登录(连接)到我的 Facebook 应用程序?

获得权限后的 Facebook 登录让 Safari 空白页面打开,而不是在 iOS 10 和 iOS 11 中重定向到我的应用

Cordova Facebook 登录插件