grails spring-security-oauth-facebook:0.2

Posted

技术标签:

【中文标题】grails spring-security-oauth-facebook:0.2【英文标题】: 【发布时间】:2015-02-12 11:18:31 【问题描述】:

我一直在尝试实现 grails 插件 spring-security-oauth-facebook:0.2 并且没有从 spring 插件获得成功的身份验证。我可以访问 facebook,成功输入我的凭据,但是当 facebook 重定向回我的本地站点时,我获得了分配的标准 ROLE_ANONYMOUS 并重定向到登录页面。通过 Spring Security 的标准站点登录完美运行。

I'm using Grails 2.4.4
BuildConfig.groovy applicable plugins are:
        compile ':spring-security-core:2.0-RC4'
        compile ":spring-security-oauth:2.1.0-RC4"
        compile ":spring-security-ui:1.0-RC2"
        compile ':spring-security-oauth-facebook:0.2'

Config.groovy:
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.myapp.domain.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.myapp.domain.UserRole'
grails.plugin.springsecurity.authority.className = 'com.myapp.domain.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                              ['permitAll'],
    '/index':                         ['permitAll'],
    '/index.gsp':                     ['permitAll'],
    '/assets/**':                     ['permitAll'],
    '/**/js/**':                      ['permitAll'],
    '/**/css/**':                     ['permitAll'],
    '/**/images/**':                  ['permitAll'],
    '/**/favicon.ico':                ['permitAll'],
    '/login/**':                      ['permitAll'],
    '/logout/**':                     ['permitAll'],
    '/register/**':                   ['permitAll'],
    '/oauth/**':                      ['permitAll'],
    '/oauth/facebook/**':             ['permitAll']
]

def appName = 'myapp'
def baseURL = grails.serverURL ?: "(myurl):$System.getProperty('server.port', '8050')/$appName"
oauth 
  debug = true
  providers 
      facebook 
          api = gweb.FaceBookCustomAPI
          key = 'my-key'
          secret = 'my-seceret'
          successUri = "/oauth/facebook/success"
          failureUri = "/oauth/facebook/failure"
          callback = "$baseURL/oauth/facebook/callback"
      
  

// Added by the Spring Security OAuth plugin:
grails.plugin.springsecurity.oauth.domainClass = 'com.myapp.domain.OAuthID'

当我点击 facebook 链接登录时(网址:/oauth/facebook/authenticate?redirectUrl=),我得到以下日志:

....matcher.AntPathRequestMatcher Request '/oauth/facebook/authenticate' matched by universal pattern '/**'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
context.HttpSessionSecurityContextRepository No HttpSession currently exists
context.HttpSessionSecurityContextRepository No SecurityContext was available from the HttpSession: null. A new one will be created.
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 3 of 8 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 4 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 5 of 8 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 6 of 8 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
intercept.FilterSecurityInterceptor Secure object: FilterInvocation: URL: /oauth/facebook/authenticate?redirectUrl=; Attributes: [permitAll]
intercept.FilterSecurityInterceptor Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc4337e: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
hierarchicalroles.RoleHierarchyImpl getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
intercept.FilterSecurityInterceptor Authorization successful
intercept.FilterSecurityInterceptor RunAsManager did not change Authentication object
web.FilterChainProxy /oauth/facebook/authenticate?redirectUrl= reached end of additional filter chain; proceeding with original chain
gweb.FaceBookCustomAPI AuthorizationUrl: facebook.com/dialog/oauth?client_id=123MYCLIENTID123&redirect_uri=http%3A%2F%2Flocal.myappname.com%3A8050%2Fgweb%2Foauth%2Ffacebook%2Fcallback api key: 123MYCLIENTID123 seceret: d3996df187347f9f6b8021dd223acdf5
access.ExceptionTranslationFilter Chain processed normally
context.HttpSessionSecurityContextRepository SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
context.SecurityContextPersistenceFilter SecurityContextHolder now cleared, as request processing completed
matcher.AntPathRequestMatcher Request '/oauth/facebook/callback' matched by universal pattern '/**'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
context.HttpSessionSecurityContextRepository HttpSession returned null object for SPRING_SECURITY_CONTEXT
context.HttpSessionSecurityContextRepository No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@28b44fe3. A new one will be created.
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 3 of 8 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 4 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 5 of 8 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 6 of 8 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
intercept.FilterSecurityInterceptor Secure object: FilterInvocation: URL: /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw; Attributes: [permitAll]
intercept.FilterSecurityInterceptor Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc6f3f8: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@255f8: RemoteIpAddress: 127.0.0.1; SessionId: AE8351B5D34F45ED370ED63F6FB7C3A8; Granted Authorities: ROLE_ANONYMOUS
hierarchicalroles.RoleHierarchyImpl getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
intercept.FilterSecurityInterceptor Authorization successful
intercept.FilterSecurityInterceptor RunAsManager did not change Authentication object
web.FilterChainProxy /oauth/facebook/callback?code=AQCgtBI6VeUcWF7xUN5G4n9IU3Owyjm9HiM3OiPWvI2-w5FILyeqNEYPKOgDVGvyLShnNBcwzTjgPuJLls-9VFXrVCQrH4nWOzbUmUukoJVusMQUXhX6fjO_XY8a21VuJh9RkpTg-isZCSSEe86Nz9rbF4c9NK_-GRUa0onNwAbzvMSUG-IqzfzZaxyFoDcBWxS6VDuZrqVyFKEiTa0mgDjRgCZ077KMLdWJn8tWB8E9jR59CnWrvpXvfpcHz4w5NWmfmKE7Johh9ymYn8YeLr0L_7OlSydDQAyO-ERJf2JTvraQzNY0e-CA2SxTWL4lVxw reached end of additional filter chain; proceeding with original chain
gweb.FaceBookCustomAPI accessTokenEndpoint: https://graph.facebook.com/oauth/access_token
access.ExceptionTranslationFilter Chain processed normally
context.HttpSessionSecurityContextRepository SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
context.SecurityContextPersistenceFilter SecurityContextHolder now cleared, as request processing completed
matcher.AntPathRequestMatcher Request '/oauth/facebook/success' matched by universal pattern '/**'
web.FilterChainProxy /oauth/facebook/success at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
context.HttpSessionSecurityContextRepository HttpSession returned null object for SPRING_SECURITY_CONTEXT
context.HttpSessionSecurityContextRepository No SecurityContext was available from the HttpSession: org.apache.catalina.session.StandardSessionFacade@28b44fe3. A new one will be created.
web.FilterChainProxy /oauth/facebook/success at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
web.FilterChainProxy /oauth/facebook/success at position 3 of 8 in additional filter chain; firing Filter: 'RequestHolderAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/success at position 4 of 8 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
web.FilterChainProxy /oauth/facebook/success at position 5 of 8 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/success at position 6 of 8 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
web.FilterChainProxy /oauth/facebook/success at position 7 of 8 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
web.FilterChainProxy /oauth/facebook/success at position 8 of 8 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
intercept.FilterSecurityInterceptor Secure object: FilterInvocation: URL: /oauth/facebook/success; Attributes: [_DENY_]
intercept.FilterSecurityInterceptor Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc6f3f8: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@255f8: RemoteIpAddress: 127.0.0.1; SessionId: AE8351B5D34F45ED370ED63F6FB7C3A8; Granted Authorities: ROLE_ANONYMOUS
hierarchicalroles.RoleHierarchyImpl getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
access.ExceptionTranslationFilter Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at grails.plugin.springsecurity.access.vote.AuthenticatedVetoableDecisionManager.decide(AuthenticatedVetoableDecisionManager.java:47)
    at grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter.doFilter(GrailsAnonymousAuthenticationFilter.java:53)
    at grails.plugin.springsecurity.web.authentication.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:49)
    at grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:82)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
savedrequest.HttpSessionRequestCache DefaultSavedRequest added to Session: DefaultSavedRequest[http://local.myappname.com:8050/gweb/oauth/facebook/success]
access.ExceptionTranslationFilter Calling Authentication entry point.
web.DefaultRedirectStrategy Redirecting to 'local.myappname.com:8050/gweb/login/auth'
context.HttpSessionSecurityContextRepository SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
context. ..... this seems to repeat a couple more times...

我很茫然,好像 Facebook 身份验证正在工作。我可以终止我的 FB 会话/从我的个人资料中删除应用程序,当我尝试从我的站点验证 URL 时,一切似乎都正常,但我总是被重定向到带有上述日志的登录屏幕。我是否遗漏了实施的某些部分?

【问题讨论】:

所以当 FB 回复回调 url 时,处理回调的代码必须重新认证用户。您必须在某处保存 fb 信息并以某种方式与您自己的用户绑定。我所做的是捕获 FB uid,将其保存为关联到我自己的用户,然后调用以下命令: springSecurityService.reauthenticate("some user name") 我的所有用户都有一个唯一的用户名。 【参考方案1】:

几天来我一直在遇到同样的问题,但我想我已经解决了:答案是插件似乎没有正确处理“注释”securityConfigType。

所以,为了让它工作,你需要改变: grails.plugin.springsecurity.securityConfigType = "注解" 到 grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"

然后您需要将 grails.plugin.springsecurity.controllerAnnotations.staticRules 配置转换为 grails.plugin.springsecurity.interceptUrlMap,然后将基于注释的安全性从控制器移植到此配置。

这是我可以让这个插件真正工作的唯一方法。希望这会有所帮助。

【讨论】:

以上是关于grails spring-security-oauth-facebook:0.2的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 grails 命令行编译 grails 项目?

是否可以在 Grails 之外使用 Grails 验证?如何?

Grails:企业级 Grails [关闭]

Grails - grails.converters.JSON - 删除类名

Grails - 在刷新 grails 错误之前保存瞬态实例?

Grails 3 - 资源插件