Java Spring Security 的编程使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1013032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:17:03  来源:igfitidea点击:

Programmatic use of Spring Security

javaspringspring-securitywicket

提问by

I am using Wicketwith the Wicket Auth Project for my presentation layer and I have therefore integrated it with Spring Security. This is the method which is called by Wicket for authentication for me:

我将Wicket与 Wicket Auth Project 用于我的表示层,因此我已将其与 Spring Security 集成。这是 Wicket 为我调用的身份验证方法:

@Override
public boolean authenticate(String username, String password) {
    try {
        Authentication request = new UsernamePasswordAuthenticationToken(
                username, password);
        Authentication result = authenticationManager.authenticate(request);
        SecurityContextHolder.getContext().setAuthentication(result);
    } catch (AuthenticationException e) {
        return false;
    }
    return true;
}

The contents (inside ) of my Spring Security XML configuration are:

我的 Spring Security XML 配置的内容(里面)是:

<http path-type="regex">
    <form-login login-page="/signin"/>
<logout logout-url="/logout" />
</http>
<global-method-security secured-annotations="enabled" />
<authentication-manager alias="authenticationManager"/>
<authentication-provider user-service-ref="userService">
    <password-encoder ref="bcryptpasswordencoder" />
</authentication-provider>

The section 2.3.6. Session Fixation Attack Protectionof the reference documentation says:

2.3.6参考文档的Session Fixation Attack Protection说:

Session fixation attacks are a potential risk where it is possible for a malicious attacker to create a session by accessing a site, then persuade another user to log in with the same session (by sending them a link containing the session identifier as a parameter, for example). Spring Security protects against this automatically by creating a new session when a user logs in. If you don't require this protection, or it conflicts with some other requirement, you can control the behaviour using the session-fixation-protection attribute on , which has three options:

  • migrateSession - creates a new session and copies the existing session attributes to the new session. This is the default.
  • none - Don't do anything. The original session will be retained.
  • newSession - Create a new "clean" session, without copying the existing session data.

会话固定攻击是一种潜在风险,恶意攻击者有可能通过访问站点来创建会话,然后说服另一个用户使用同一会话登录(通过向他们发送包含会话标识符作为参数的链接,对于例子)。Spring Security 通过在用户登录时创建一个新会话来自动防止这种情况。如果您不需要这种保护,或者它与其他一些要求冲突,您可以使用 session-fixation-protection 属性来控制行为,它有三个选项:

  • migrateSession - 创建一个新会话并将现有会话属性复制到新会话。这是默认设置。
  • none - 什么都不做。原始会话将被保留。
  • newSession - 创建一个新的“干净”会话,而不复制现有的会话数据。

The authentication works, but I as I'm fairly new to Spring Security I have some questions which I need answers too:

身份验证有效,但由于我对 Spring Security 还很陌生,所以我也有一些问题需要回答:

  • Normally for login, I would POST the authentication information to j_spring_security_checkand let Spring Security perform the actual authentication code. I would like to have protection against session fixation attacks, will I get it when I perform a programmatic login as I do? And if not, what would I have to do to get it?
  • How do I perform programmatic logout?
  • As I will use programmatic login and logout, how do I disable Spring from intercepting those URL's?
  • 通常对于登录,我会将身份验证信息 POST 到j_spring_security_check并让 Spring Security 执行实际的身份验证代码。我想要防止会话固定攻击,当我像我一样执行程序化登录时,我会得到它吗?如果没有,我需要做什么才能得到它?
  • 如何执行程序化注销?
  • 由于我将使用程序化登录和注销,我如何禁用 Spring 拦截这些 URL?

Update:For session fixation attack protection it seems that I need to call the method in the SessionUtils class with the signature startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry).

更新:对于会话固定攻击保护,似乎我需要使用签名调用 SessionUtils 类中的方法startNewSessionIfRequired(HttpServletRequest request, boolean migrateAttributes, SessionRegistry sessionRegistry)

How do I get the SessionRegistry instance which I need to pass in? I can't find any way to create an alias ID for it, or how to get it's ID or name.

如何获取需要传入的 SessionRegistry 实例?我找不到任何方法来为它创建别名 ID,或者如何获取它的 ID 或名称。

采纳答案by Grzegorz Oledzki

Maybe it's not a full answer to your questions, but maybe it might help you.

也许这不是您问题的完整答案,但也许可以帮助您。

The code being called when you do NOT use programmatic login, but a standard one is to be found here:

当您不使用程序登录时调用的代码,但可以在此处找到标准的代码:

org.springframework.security.ui.webapp.AuthenticationProcessingFilter

org.springframework.security.ui.webapp.AuthenticationProcessingFilter

I guess you were inspired by this in your code. It looks quite similar.

我猜你在你的代码中受到了这一点的启发。它看起来非常相似。

Similarly the code executed when you access the /j_spring_security_logoutin the standard approach, is to be found here:

类似地/j_spring_security_logout,在标准方法中访问 时执行的代码可在此处找到:

org.springframework.security.ui.logout.LogoutFilter

org.springframework.security.ui.logout.LogoutFilter

The LogoutFilter calls multiple handlers. The handler we are using is called: org.springframework.security.ui.logout.SecurityContextLogoutHandler, so you might call the same code in your approach.

LogoutFilter 调用多个处理程序。我们正在使用的处理程序称为: org.springframework.security.ui.logout.SecurityContextLogoutHandler,因此您可以在您的方法中调用相同的代码。

回答by Pablojim

You will indeed be open to session fixations attacks. To remedy this you could again be "inspired" by the Spring code. To create a new session you'll obviously need access to the httpsession so you may have to do some refactoring.

您确实会对会话固定攻击持开放态度。为了解决这个问题,您可以再次受到 Spring 代码的“启发”。要创建一个新会话,您显然需要访问 httpsession,因此您可能需要进行一些重构。

If you see the method SessionUtils.startNewSessionIfRequired.

如果你看到方法SessionUtilsstartNewSessionIfRequired.

This will migrate the authentication to a new session. You might be able to call this method directly or else just refactor the code a little.

这会将身份验证迁移到新会话。您也许可以直接调用此方法,或者只是稍微重构一下代码。

As for programmatic logout you can't go too far wrong by simply calling session.invalidate()when you need to log the person out. This will do everything necessary from a general security perspective but bear in mind though you might need to cleanup some things on the session. If you have a very complicated set of filters etc. and you need to ensure that that the user is logged out for the rest of the request then you could add:

至于程序化注销,您只需session.invalidate()在需要注销此人时调用,就不会出错。从一般安全角度来看,这将完成所有必要的操作,但请记住,尽管您可能需要清理会话中的某些内容。如果您有一组非常复杂的过滤器等,并且您需要确保用户在请求的其余部分已注销,那么您可以添加:

SecurityContextHolder.getContext().setAuthentication(null);

As for interception of the url's you could just set them to something unused and ignore it! I'm not sure if you can turn off the interception in configuration - if you really want to remove it then have a look at the AuthenticationProcessingFilter- you could customise this. If you do this then you'll have to manually setup the spring security xml and not use the provided namespaces. It's not too hard though - look at some older documentation and you'll see how to do this.

至于拦截网址,您可以将它们设置为未使用的内容并忽略它!我不确定您是否可以在配置中关闭拦截-如果您真的想删除它,请查看AuthenticationProcessingFilter-您可以自定义它。如果这样做,则必须手动设置 spring 安全性 xml,而不是使用提供的命名空间。不过这并不太难 - 查看一些较旧的文档,您将了解如何执行此操作。

Hope this helps!

希望这可以帮助!

回答by Gandalf

1) Programmatic Logout

1) 程序化注销

  1. call HttpServletRequest.getSession(false).invalidate
  2. call SecurityContextHolder.clearContext()
  1. 调用 HttpServletRequest.getSession(false).invalidate
  2. 调用 SecurityContextHolder.clearContext()

2) Tell Spring Security NOT to intercept certain URLs, this one kind of depends on how your application url space is setup. If all your pages (except /logIn and /logout) lived at the context /myApp then you could do this:

2) 告诉 Spring Security 不要拦截某些 URL,这取决于您的应用程序 url 空间是如何设置的。如果您的所有页面(/logIn 和 /logout 除外)都位于上下文 /myApp 中,那么您可以执行以下操作:

<http ....>
  <intercept-url pattern="/myApp/**" ..>
 ....
</http>

回答by viator

To do programmatic logout it's also possible to throw an org.springframework.security.core.AuthenticationException. For example, SessionAuthenticationException. In this case ExceptionTranslationFilterinitiate logout.

要进行程序化注销,也可以抛出org.springframework.security.core.AuthenticationException. 例如,SessionAuthenticationException。在这种情况下ExceptionTranslationFilter启动注销。

回答by velaia

I had an issue with programmatic login. I called all the authenticationManager.authenticate(...)and SecurityContextHolder.getContext().setAuthentication(...)methods but had some issues with the Session. I had to add the following lines to properly manage the session:

我遇到了程序化登录的问题。我调用了所有的authenticationManager.authenticate(...)SecurityContextHolder.getContext().setAuthentication(...)方法,但是 Session 有一些问题。我必须添加以下几行才能正确管理会话:

HttpSession session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());

This was not clear from the example code posted above. For more look at http://forum.springsource.org/showthread.php?t=69761

从上面发布的示例代码中并不清楚这一点。有关更多信息,请访问http://forum.springsource.org/showthread.php?t=69761

回答by Chandra

You can try this

你可以试试这个

    try {
        HttpSession session = request.getSession(false);
        if (session != null) {
            session.invalidate();
        }

        SecurityContextHolder.clearContext();

    } catch (Exception e) {
        logger.log(LogLevel.INFO, "Problem logging out.");
    }