【问题标题】:Accessing Authentication variable from LogoutHandler or LogoutFilter in Spring security在 Spring security 中从 LogoutHandler 或 LogoutFilter 访问 Authentication 变量
【发布时间】:2012-02-24 11:15:34
【问题描述】:

在我的一个项目中,我配置了 Spring Security 来处理用户身份验证。

我的配置文件如下所示:

<http use-expressions="true">
    <intercept-url pattern="/" access="permitAll()" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <form-login default-target-url="/main" login-page="/" always-use-default-target="true" username-parameter="userId" password-parameter="password" />
    <custom-filter ref="customLogoutFilter" position="LOGOUT_FILTER"/-->
    <session-management invalid-session-url="/" session-authentication-strategy-ref="sas" />
</http>

<beans:bean id="sas" class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />

<beans:bean id="customLogoutHandler" class="com.somepack.CustomLogoutHandler"/>

<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <beans:constructor-arg index="0" ref="customLogoutHandler"/>
    <beans:constructor-arg index="1" ref="customLogoutFilter"/>
    <beans:property name="filterProcessesUrl" value="/"/>
</beans:bean>

<beans:bean id="customLogoutFilter" class="com.somepack.CustomLogoutFilter">
    <beans:property name="reportDir" value="/tmp/reports"/> 
</beans:bean>

我的 CustomLogoutFilter 类看起来像

public class CustomLogoutFilter implements LogoutHandler {
    private String reportDir;
    public String getReportDir() {
        return reportDir;
    }
    public void setReportDir(String reportDir) {
        this.reportDir = reportDir;
    }
    @Override
    public void logout(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication) {
        String userName = authentication.getName();
        File folder = new File(reportDir, userName);
        deleteDir(folder); //delete function to delete Logged User specific directory
        logService.info("Logout", userName, EventCode.LOGOUT,
                String.format("User %s logged out successfully", userName));
        for (Cookie cookie : request.getCookies()) {
            printcookies(cookie);
            if (cookie.equals("JSESSIONID")) {
                cookie.setMaxAge(0);
                response.addCookie(cookie);
            }
        }
        request.getSession().invalidate();
    }   
}

但是这段代码不起作用,因为过滤器在登录页面的第一个请求中被调用(即使它可能会在每个请求中被调用)并且我在 String userName = authentication.getName() 行。

事实上,如果我使用 Logouthandler 而不是使用 LogoutFilter,我会得到同样的错误:

我的处理程序如下所示:

public class CustomLogoutHandler extends AbstractAuthenticationTargetUrlRequestHandler implements LogoutSuccessHandler{
    private String reportDir;
    public String getReportDir() {
        return reportDir;
    }
    public void setReportDir(String reportDir) {
        this.reportDir = reportDir;
    }
    @Override
    public void onLogoutSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication) throws IOException,
            ServletException {
        String userName = authentication.getName();
        File folder = new File(reportDir, userName);
        deleteDir(folder);
        logService.info("Logout", userName, EventCode.LOGOUT, String.format("User %s logged out successfully", userName));
        super.handle(request, response, authentication);
    }

配置文件改为:

<http use-expressions="true">
    <intercept-url pattern="/" access="permitAll()" />
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <form-login default-target-url="/main" login-page="/" always-use-default-target="true" username-parameter="userId" password-parameter="password" />
    <logout delete-cookies="JSESSIONID" invalidate-session="true" success-handler-ref="customLogoutHandler" logout-url="/logout" />
    <session-management invalid-session-url="/" session-authentication-strategy-ref="sas" />
</http>

<beans:bean id="customLogoutHandler" class="sequent.ui.security.CustomLogoutHandler">
    <beans:property name="reportDir" value="/tmp/reports" />
</beans:bean>

不知道如何解决这个问题。

请帮忙。

简而言之,我的基本要求是,我需要在用户单击注销按钮或会话到期时触发的注销机制中访问用户主体。我需要用户信息,因为应用程序会以登录用户的名义创建临时文件夹,我需要在他注销时将其删除。

感谢您的帮助!!

-劳尔

【问题讨论】:

    标签: authentication spring-security


    【解决方案1】:

    您已将LogoutFilterfilerProcessesUrl 设置为“/”,这意味着每次用户浏览到域根目录时,过滤器都会尝试注销该用户。使用特定的注销 URL(或默认值)并在尝试注销之前检查用户是否实际经过身份验证(确保 Authentication 实例不为空)。

    如果您需要处理用户无法注销的会话超时,那么您还必须实现一个HttpSessionListener,它可以从会话中识别用户并执行您需要的任何清理工作。这将被添加到您的web.xml 文件中。请注意,在用户请求期间不会调用此类,因此您不能使用SecurityContext 获取有关用户的信息,您必须从会话对象中获取它,该对象在会话无效之前传递给侦听器。

    【讨论】:

      猜你喜欢
      • 2018-04-14
      • 2014-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      • 2012-02-28
      • 2014-07-31
      相关资源
      最近更新 更多