使用 Spring Security 处理成功的登录事件

Posted

技术标签:

【中文标题】使用 Spring Security 处理成功的登录事件【英文标题】:handle successful login event with spring security 【发布时间】:2014-01-12 21:56:06 【问题描述】:

我的 Grails 应用程序使用 Spring Security 插件。每当用户成功登录时,我想:

在会话中存储一些东西 将他们重定向到自定义页面(取决于他们的角色)

我需要类似地处理注销事件,这非常简单,因为插件提供了一个名为 logoutSuccessHandler 的 bean,它可以被覆盖。我希望同样能找到一个名为 loginSuccessHandler 的 bean,但没有这样的运气。

我阅读了插件文档中关于 event handling 的页面,但似乎没有一种事件处理机制允许我访问当前请求或会话。

【问题讨论】:

你用的是什么版本的插件? 【参考方案1】:

如果您想在成功登录后做一些事情。您可以收听 InteractiveAuthenticationSuccessEvent

class AuthenticationSuccessEventListener implements    
                       ApplicationListener<InteractiveAuthenticationSuccessEvent> 


    @Override
    public void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) 
         .......do some stuff here
    
   

然后将AuthenticationSuccessEventListener注册为resources.groovy中的spring bean 你可以在这里做任何你想做的事情,但是你不能从监听器做重定向。

这是另一个类似的question

【讨论】:

他可以从这里访问会话吗? 您可以从SecurityRequestHolder.request.session访问会话【参考方案2】:

添加配置参数:

grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/myLogin/handleSuccessLogin'

然后在处理此 URL 的操作中添加您的自定义登录处理

class MyLoginController 

  def springSecurityService

  def handleSuccessLogin() 
    session.foo = 'bar'

    if (springSecurityService.currentUser.username == 'bob') 
      redirect action: 'bobLogin'
     else 
      redirect action: 'defaultLogin'
             
    

  def bobLogin() 
    // bob's login handler
  

  def defaultLogin() 
    // default login handler
  

【讨论】:

在登录时触发一个动作比使用监听器方法强大得多:直接访问 http 会话、动作重定向等。【参考方案3】:

我最近在一个项目中使用它来登录。它有点像黑客,但对我有用。我使用的是 1.2.7.3 版本的插件。

def auth()         

    def config = SpringSecurityUtils.securityConfig

    if (springSecurityService.isLoggedIn()) 
        def user = User.get(principal.id)

        def roles = user.getAuthorities()

        def admin_role = Role.findByAuthority("ROLE_ADMIN")

        //this user is not admin
        if(!roles.contains(admin_role))
            //perform redirect to appropriate page
        
        redirect uri: config.successHandler.defaultTargetUrl
        //log.info(getPrincipal().username + "logged in at :"+new Date())
        return
    

    String view = 'auth'
    String postUrl = "$request.contextPath$config.apf.filterProcessesUrl"
    render view: view, model: [postUrl: postUrl,
                               rememberMeParameter: config.rememberMe.parameter]

为了注销,我使用了注销控制器,在重定向到注销处理程序之前执行了一些操作:

class LogoutController 

     /**
     * Index action. Redirects to the Spring security logout uri.
     */
     def index = 
         // perform some action here
         redirect uri: SpringSecurityUtils.securityConfig.logout.filterProcessesUrl 
     

【讨论】:

LoginControllerauth 操作在成功登录后不会被回调,所以我看不到第一个代码示例对我有什么帮助? 好的。您是否能够找到解决方案?你做了什么? Sudhir 的回答看起来不错,但我没有尝试过。

以上是关于使用 Spring Security 处理成功的登录事件的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义 Spring Security 登录成功处理程序中注入会话 bean

Spring Security:无法将我的 UserDetailService 自动连接到 AuthenticationProvider 以进行 BCrypt 集成

spring-security 个性化用户认证流程——自定义登录成功/失败的处理

Spring Security教程(10)---- 自定义登录成功后的处理程序及修改默认验证地址

Spring Security6登录用户退出登录操作

使用 Spring Security 成功登录后如何将用户转发回所需的受保护页面