使用Facebook身份验证Spring Security插件处理权限不足的正确方法是什么?

时间:2014-07-18 02:48:15

标签: facebook spring grails spring-security grails-plugin

我使用Spring Security 2.0-RC4和Spring Security 0.15.2-CORE2的Facebook身份验证,允许用户通过Facebook登录进行身份验证。我要求额外的FB许可"电子邮件"因为我使用电子邮件作为我的User类的主键,所以如果用户未选择电子邮件权限,我需要中止登录。目前,我在FacebookAuthService.create()中检查空电子邮件,如果未设置电子邮件,则返回null。

在正常情况下一切正常。登录成功,我创建了新的用户和FacebookUser记录,并且用Facebook用户的电子邮件地址更新了我的用户对象的电子邮件属性。但是,如果用户在登录期间选择删除电子邮件权限,则会遇到问题。

在我的FacebookAuthService.create()中,我检查是否返回了电子邮件(类似于in this question),如果没有,则返回null以中止身份验证过程:

FacebookUser create(FacebookAuthToken token) {
    Facebook facebook
    FacebookProfile fbProfile
    try {
        facebook = new FacebookTemplate(token.accessToken.accessToken)
        fbProfile = facebook.userOperations().userProfile
    } catch (org.springframework.social.ApiException apiex) {
        return null
    }
    String email = fbProfile.email

    if (!email) {
        return null
    }
    ...

当电子邮件为空并且我返回null时,我的安全状态似乎搞砸了。我的控制器上有一个beforeInterceptor,在我从create()返回null之后调用它:

def beforeInterceptor = {
    def user = springSecurityService.currentUser
    log.trace("${user?.email} - End action ${controllerName}Controller.${actionName}() : returns $model, view ${modelAndView?.viewName}")
}

getCurrentUser()应该返回null,而是抛出异常:

org.codehaus.groovy.grails.web.errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [GET] /rar/user/home
Cannot get property 'username' on null object. Stacktrace follows:
java.lang.NullPointerException: Cannot get property 'username' on null object
    at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56)
    at org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:169)
    at org.codehaus.groovy.runtime.callsite.NullCallSite.getProperty(NullCallSite.java:44)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
    at grails.plugin.springsecurity.SpringSecurityService.getCurrentUser(SpringSecurityService.groovy:87)

    at grails.plugin.springsecurity.SpringSecurityService$$FastClassBySpringCGLIB$$6e53ab8e.invoke(<generated>)
...

SpringSecurityService似乎认为有人已登录,因为getCurrentUser()isLoggedIn()的调用返回true,这会导致稍后当principal为null并且访问属性时出现异常null主要对象。

我是否应该以不同的方式中止Facebook登录过程,而不是从FacebookAuthService.create()返回null?

1 个答案:

答案 0 :(得分:0)

通过从FacebookAuthService.create()抛出异常而不是在删除电子邮件权限时返回null来解决此问题。

我的create()现在包含以下代码段:

if (!email) {
    def grailsWebRequest = WebUtils.retrieveGrailsWebRequest()
    def flash = grailsWebRequest.flashScope
    flash.message = 'Login to Facebook failed. We must have access to your email address in order to proceed with login.'
        throw new InsufficientAuthenticationException()
}