Grails Spring Security:使用目标 URL 登录会跳过认证后工作流程 [英] Grails Spring Security: Logging in with a target URL skips post authentication workflow

查看:35
本文介绍了Grails Spring Security:使用目标 URL 登录会跳过认证后工作流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的 grails 应用程序中,我通过编写自定义身份验证成功处理程序(在 resources.groovy 中)自定义了授权后工作流程,如下所示.

In my grails app I have customized the post authorization workflow by writing a custom auth success handler (in resources.groovy) as shown below.

authenticationSuccessHandler (MyAuthSuccessHandler) {
    def conf = SpringSecurityUtils.securityConfig
    requestCache = ref('requestCache')
    defaultTargetUrl = conf.successHandler.defaultTargetUrl
    alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
    targetUrlParameter = conf.successHandler.targetUrlParameter
    useReferer = conf.successHandler.useReferer
    redirectStrategy = ref('redirectStrategy')
    superAdminUrl = "/admin/processSuperAdminLogin"
    adminUrl = "/admin/processAdminLogin"
    userUrl = "/admin/processUserLogin"
}

从上面闭包的最后三行可以看出,根据授予登录用户的角色,我将她重定向到 AdminController 中的单独操作,其中创建了自定义 UserSessionBean 和存储在会话中.

As you can from the last three lines in the closure above, depending on the Role granted to the logging in User I am redirecting her to separate actions within the AdminController where a custom UserSessionBean is created and stored in the session.

它适用于我的应用程序中的常规登录案例:

It works fine for a regular login case which in my app is like so:

  1. 用户通过 http://localhost:8080/my-app/http://localhost:8080/my-app/login/auth 访问应用程序代码>
  2. 她输入了她的有效登录 ID 和密码,然后继续.
  3. 应用在内部访问 MyAuthSuccessHandler,考虑授予该用户的角色,MyAuthSuccessHandler 重定向到 AdminController.
  4. 创建 UserSessionBean 并将其存储在会话中
  5. 用户被带到应用主页

我还通过扩展在上述流程中正确访问的 GormUserDetailsS​​ervice 编写了一个自定义 MyUserDetailsS​​ervice.

I have also written a custom MyUserDetailsService by extending GormUserDetailsService which is correctly accessed in the above flow.

问题情景:
考虑用户直接访问应用内受保护的资源(在这种情况下,控制器使用 @Secured 注释保护).

  1. 用户点击http://localhost:8080/my-app/inbox/index
  2. App 将她重定向到 http://localhost:8080/my-app/login/auth
  3. 用户输入她的有效登录 ID 和密码
  4. 用户被带到http://localhost:8080/my-app/inbox/index

MyAuthSuccessHandler 在这个过程中被完全跳过,因此我的 UserSessionBean 没有被创建,导致在 UserSessionBean 的地方进一步使用时出错被访问.

The MyAuthSuccessHandler is skipped entirely in this process and hence my UserSessionBean is not created leading to errors upon further use in places where the UserSessionBean is accessed.

问题:

  1. 在问题场景中,应用是否跳过了 MyAuthSuccessHandler,因为它有一个目标 URL 可以在登录时重定向到?
  2. 即使存在目标 URL,我们能否强制进程始终通过 MyAuthSuccessHandler?
  3. 如果 2 的答案是否定的,是否还有其他方法可以创建 UserSessionBean,以及在何处创建?
  1. In the problem scenario, does the app skip the MyAuthSuccessHandler because there is a target URL for it to redirect to upon login?
  2. Can we force the process to always pass through MyAuthSuccessHandler even with the target URL present?
  3. If the answer to 2 is no, is there an alternative as to how and where the UserSessionBean can still be created?

推荐答案

您可以实现自定义的 eventListener 来处理登录后过程,而不会中断原始用户请求的 url.

You can implement a customized eventListener to handle the post-login process, without disrupting the original user requested url.

在 config.groovy 中,插入一个配置项:

In config.groovy, insert a config item:

grails.plugins.springsecurity.useSecurityEventListener = true

在你的resources.groovy中,像这样添加一个bean:

In you resources.groovy, add a bean like this:

import com.yourapp.auth.LoginEventListener
beans = {
    loginEventListener(LoginEventListener)
}

然后在 src/groovy 中创建一个 eventListener,如下所示:

And create a eventListener in src/groovy like this:

package com.yourapp.auth
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent
import org.springframework.web.context.request.RequestContextHolder as RCH

class LoginEventListener implements
    ApplicationListener<InteractiveAuthenticationSuccessEvent> {    

    //deal with successful login    
    void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
        User.withTransaction { 
            def user = User.findByUsername(event.authentication.principal.username)
                    def adminRole = Role.findByAuthority('ROLE_ADMIN')
                    def userRole = Role.findByAuthority('ROLE_USER')
                    def session = RCH.currentRequestAttributes().session      //get httpSession
                    session.user = user
                    if(user.authorities.contains(adminRole)){
                        processAdminLogin()
                    }
                    else if(user.authorities.contains(userRole)){
                        processUserLogin()
                    }
        }
    }

    private void processAdminLogin(){    //move admin/processAdminLogin here
          .....
    }

    private void processUserLogin(){    //move admin/processUserLogin here
          .....
    }
}

完成.

这篇关于Grails Spring Security:使用目标 URL 登录会跳过认证后工作流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆