欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用Spring Security控制会话的方法

程序员文章站 2023-11-26 23:55:16
1.概述 在本文中,我们将说明spring security如何允许我们控制http会话。此控件的范围从会话超时到启用并发会话和其他高级安全配置。 2.会话何时创建?...

1.概述

在本文中,我们将说明spring security如何允许我们控制http会话。此控件的范围从会话超时到启用并发会话和其他高级安全配置。

2.会话何时创建?

我们可以准确控制会话何时创建以及spring security如何与之交互:

•always - 如果一个会话尚不存在,将始终创建一个会话
•ifrequired - 仅在需要时创建会话(默认)
•never - 框架永远不会创建会话本身,但如果它已经存在,它将使用一个
•stateless - spring security不会创建或使用任何会话

<http create-session="ifrequired">...</http>

java配置:

@override
protected void configure(httpsecurity http) throws exception {
  http.sessionmanagement()
    .sessioncreationpolicy(sessioncreationpolicy.if_required)
}

了解此配置仅控制spring security的功能非常重要 - 而不是整个应用程序。如果我们不指示spring security,可能无法创建会话,但我们的应用程序可能会!

默认情况下,spring security会在需要时创建会话 - 这是“ifrequired”。

对于更无状态的应用程序,“never”选项将确保spring security本身不会创建任何会话;但是,如果应用程序创建了一个,那么spring security将使用它。

最后,最严格的会话创建选项 - “stateless” - 保证应用程序根本不会创建任何会话。

这是在spring 3.1中引入的,它将有效地跳过部分spring security过滤器链。主要是会话相关的部分,如

httpsessionsecuritycontextrepository,sessionmanagementfilter,requestcachefilter。

这些更严格的控制机制直接暗示不使用cookie,所以每个请求都需要重新进行身份验证。这种无状态架构适用于rest api及其无状态约束。它们也适用于基本和摘要式身份验证等身份验证机制。

3. under the hood

在执行身份验证过程之前,spring security将运行一个负责在请求之间存储安全上下文的过滤器-securitycontextpersistencefilter。上下文将根据策略存储 - 默认情况下为httpsessionsecuritycontextrepository - 它使用http会话作为存储。对于strict create-session =“stateless”属性,此策略将替换为另一个 - nullsecuritycontextrepository - 并且不会创建或使用会话来保留上下文。

4.并发会话控制

当已经过身份验证的用户尝试再次进行身份验证时,应用程序可以通过以下几种方式之一处理该事件。它可以使用户的活动会话无效,并使用新会话再次对用户进行身份验证,或者允许两个会话同时存在。

启用并发会话控制支持的第一步是在web.xml中添加以下侦听器:

<listener>
  <listener-class>
   org.springframework.security.web.session.httpsessioneventpublisher
  </listener-class>
</listener>

或者将其定义为bean - 如下所示:

@bean
public httpsessioneventpublisher httpsessioneventpublisher() {
  return new httpsessioneventpublisher();
}

这对于确保在销毁会话时通知spring security会话注册表是至关重要。

要为同一用户启用允许多个并发会话的方案,应在xml配置中使用元素:

<http ...>
  <session-management>
    <concurrency-control max-sessions="2" />
  </session-management>
</http>

或者,通过java配置:

@override
protected void configure(httpsecurity http) throws exception {
  http.sessionmanagement().maximumsessions(2)
}

5.会话超时

会话超时后,如果用户发送的会话id已过期,则会将其重定向到可通过命名空间配置的url:

<session-management>
  <concurrency-control expired-url="/sessionexpired.html" ... />
</session-management>

同样,如果用户发送的会话id未过期但完全无效,则它们也会被重定向到可配置的url:

<session-management invalid-session-url="/invalidsession.html">
  ...
</session-management>

相应的java配置:

http.sessionmanagement()
 .expiredurl("/sessionexpired.html")
 .invalidsessionurl("/invalidsession.html");

6.防止使用url参数进行会话跟踪

在url中公开会话信息的安全风险越来越大(从2007年的第7位到2013年在owasp排行榜前10位的第2位)。

从spring 3.0开始,现在可以通过在命名空间中设置disable-url-rewriting =“true”来禁用将jsessionid附加到url的url重写逻辑。

或者,从servlet 3.0开始,也可以在web.xml中配置会话跟踪机制:

<session-config>
   <tracking-mode>cookie</tracking-mode>
</session-config>

编程方式

servletcontext.setsessiontrackingmodes(enumset.of(sessiontrackingmode.cookie));

这将选择存储jsessionid的位置 - 在cookie或url参数中。

7. spring security的会话固定保护

该框架通过配置在用户已有会话的情况但尝试再次进行身份验证时,提供了针对典型会话固定攻击的保护:

<session-management session-fixation-protection="migratesession"> ...

相应的java配置:

http.sessionmanagement()
 .sessionfixation().migratesession()

默认情况下,spring security启用了此保护(“migratesession”) - 在身份验证时,会创建一个新的http会话,旧的会话将失效,旧会话的属性将被复制。

如果这不是所需的行为,则可以使用其他两个选项:

•设置“none”时,原始会话不会失效
•设置“newsession”时,将创建一个干净的会话,而不会复制旧会话中的任何属性

8.安全会话cookie

接下来,我们将讨论如何保护会话cookie。

我们可以使用httponly和secure标签来保护我们的会话cookie:

•httponly:如果为true,那么浏览器脚本将无法访问cookie
•secure:如果为true,则cookie将仅通过https连接发送

我们可以在web.xml中为会话cookie设置这些标志:

<session-config>
  <session-timeout>1</session-timeout>
  <cookie-config>
    <http-only>true</http-only>
    <secure>true</secure>
  </cookie-config>
</session-config>

从java servlet 3开始,此配置选项可用。默认情况下,http-only为true且secure为false。

我们来看看相应的java配置:

public class mainwebappinitializer implements webapplicationinitializer {
  @override
  public void onstartup(servletcontext sc) throws servletexception {
    // ...
    sc.getsessioncookieconfig().sethttponly(true);    
    sc.getsessioncookieconfig().setsecure(true);    
  }
}

如果我们使用spring boot,我们可以在application.properties中设置这些标志:

server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=true

最后,我们还可以使用filter手动实现此目的:

public class sessionfilter implements filter {
  @override
  public void dofilter(servletrequest request, servletresponse response, filterchain chain)
   throws ioexception, servletexception {
    httpservletrequest req = (httpservletrequest) request;
    httpservletresponse res = (httpservletresponse) response;
    cookie[] allcookies = req.getcookies();
    if (allcookies != null) {
      cookie session = 
       arrays.stream(allcookies).filter(x -> x.getname().equals("jsessionid"))
          .findfirst().orelse(null);
 
      if (session != null) {
        session.sethttponly(true);
        session.setsecure(true);
        res.addcookie(session);
      }
    }
    chain.dofilter(req, res);
  }
}

9.session使用

9.1。 session scoped beans

只需在web-context中,使用@scope注释声明的bean:

@component
@scope("session")
public class foo { .. }

或者使用xml:

<bean id="foo" scope="session"/>

然后,bean可以简单地注入另一个bean:

@autowired
private foo thefoo;

spring会将新bean绑定到http session的生命周期。

9.2。将会话注入控制器

原始http会话也可以直接注入controller方法:

@requestmapping(..)
public void foomethod(httpsession session) {
  session.addattribute(constants.foo, new foo();
  //...
  foo foo = (foo) session.getattribute(constants.foo);
}

9.3。获取会话

当前的http session也可以通过原始servlet api以编程方式获得:

servletrequestattributes attr = (servletrequestattributes) 
  requestcontextholder.currentrequestattributes();
httpsession session= attr.getrequest().getsession(true); // true == allow create

10.总结

在本文中,我们讨论了使用spring security管理sessions。此外,spring reference包含一个非常好的会话管理

与往常一样,本文中提供的代码可以在github上获得。这是一个基于maven的项目,因此它应该很容易导入和运行。

以上所述是小编给大家介绍的使用spring security控制会话的方法,希望对大家有所帮助