10.3 Servlet API integration

本节介绍如何将Spring Security 与servlet API集成。 servletapi-xml示例应用程序演示了这些方法的用法。

10.3.1 Servlet 2.5+ Integration

HttpServletRequest.getRemoteUser()

HttpServletRequest.getRemoteUser() 将返回SecurityContextHolder.getContext().getAuthentication().getName()的结果,后者通常是当前用户名。如果要在应用程序中显示当前用户名,这将非常有用。此外,可以使用检查这是否为空来指示用户是否已经过身份验证或是匿名的。知道用户是否经过身份验证对于确定是否应显示某些UI元素很有用(即,只有在用户经过身份验证时才应显示注销链接)。

HttpServletRequest.getUserPrincipal()

HttpServletRequest.getUserPrincipal() 将返回SecurityContextHolder.getContext().getAuthentication()的结果。这意味着它是一个身份验证,在使用用户名和基于密码的身份验证时,它通常是UsernamePasswordAuthenticationToken的实例。如果您需要有关用户的其他信息,这将非常有用。例如,您可能创建了一个自定义的UserDetailsService,该服务返回一个包含您的用户名字和姓氏的自定义用户详细信息。您可以通过以下方式获得此信息:

Authentication auth = httpServletRequest.getUserPrincipal();

// assume integrated custom UserDetails called MyCustomUserDetails

// by default, typically instance of UserDetails

MyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();

String firstName = userDetails.getFirstName();

String lastName = userDetails.getLastName();

应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。相反,应该集中它以减少Spring Security 和servlet API之间的任何耦合。

HttpServletRequest.isUserInRole(String)

HttpServletRequest.isUserInRole(String) 将确定SecurityContextHolder.getContext().getAuthentication().getAuthorities() 是否包含传递给 isUserInRole(string)的角色的授权。通常,用户不应将“ROLE_”前缀传入此方法,因为它是自动添加的。例如,如果要确定当前用户是否具有“ROLE_ADMIN”权限,可以使用以下内容:

boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");

这可能有助于确定是否应显示某些UI组件。例如,只有当当前用户是管理员时,才能显示管理员链接。

10.3.2 Servlet 3+ Integration

以下部分介绍Spring Security集成的servlet 3方法。

HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)

HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) 方法可以用来确保用户已经完成了身份验证。如果它们未经过身份验证,则配置的 AuthenticationEntryPoint 将用于请求用户进行身份验证(即重定向到登录页)。

HttpServletRequest.login(String,String)

HttpServletRequest.login(String,String)方法使用当前的 AuthenticationManager 对用户进行身份验证。例如,下面将尝试使用用户名“user”和密码“password”进行身份验证:

try{

    httpServletRequest.login("user","password");

}catch(ServletException e) {

    // fail to authenticate

}

如果希望Spring Security 处理失败的身份验证尝试,则不必捕获ServletException。

HttpServletRequest.logout()

HttpServletRequest.logout() 方法可用于注销当前用户。

通常这意味着 SecurityContextHolder 将被清除,HttpSession 将失效,任何“Remember Me”身份验证将被清除,等等。但是,配置的Logoothandler实现将根据您的Spring安全配置而变化。需要注意的是,在调用HttpServletRequest.logout() 之后,您仍然在改写响应。通常会重定向到欢迎页面。

AsyncContext.start(Runnable)

AsynchContext.start(Runnable) 方法,用于确保将凭据传播到新线程。使用Spring Security 的并发支持,Spring Security 将重写AsyncContext.Start(Runnable),以确保在处理Runnable时使用当前的SecurityContext。例如,以下内容将输出当前用户的身份验证:

final AsyncContext async = httpServletRequest.startAsync();

async.start(new Runnable() {

    public void run() {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        try {

            final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();

            asyncResponse.setStatus(HttpServletResponse.SC_OK);

            asyncResponse.getWriter().write(String.valueOf(authentication));

            async.complete();

        } catch(Exception e) {

            throw new RuntimeException(e);

        }

    }

});

Async Servlet Support

如果您使用的是基于Java的配置,那么您已经准备好了。如果您使用的是XML配置,则需要进行一些更新。第一步是确保已更新web.xml以至少使用3.0架构,如下所示:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

version="3.0">

</web-app>

接下来,您需要确保为处理异步请求设置了SpringSecurityFilterChain。

<filter>

<filter-name>springSecurityFilterChain</filter-name>

<filter-class>

    org.springframework.web.filter.DelegatingFilterProxy

</filter-class>

<async-supported>true</async-supported>

</filter>

<filter-mapping>

<filter-name>springSecurityFilterChain</filter-name>

<url-pattern>/*</url-pattern>

<dispatcher>REQUEST</dispatcher>

<dispatcher>ASYNC</dispatcher>

</filter-mapping>

就是这样!现在,Spring安全性将确保SecurityContext也在异步请求上传播。

那么它是如何工作的呢?如果你真的不感兴趣,可以跳过这一部分的其余部分,否则请继续阅读。其中大部分都内置于servlet规范中,但是Spring Security 做了一些调整,以确保异步请求能够正常工作。在Spring Security3.2之前,只要提交HttpServletResponse,就会自动保存SecurityContextHolder中的SecurityContext。这可能导致异步环境中出现问题。例如,考虑以下内容:

httpServletRequest.startAsync();

new Thread("AsyncThread") {

    @Override

    public void run() {

        try {

            // Do work

            TimeUnit.SECONDS.sleep(1);

            // Write to and commit the httpServletResponse

            httpServletResponse.getOutputStream().flush();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

}.start();

问题是这个线程不知道Spring Security,所以SecurityContext不会传播给它。这意味着当我们提交HttpServletResponse 时没有SecuriytContext。当Spring Security在提交httpServletResponse时自动保存SecurityContext时,它将丢失我们的登录用户。

从3.2版开始,Spring Security就足够智能,一旦调用了HttpServletRequest.StartAsync(),就不会在提交HttpServletResponse时自动保存SecurityContext。

10.3.3 Servlet 3.1+ Integration

以下部分介绍Spring Security集成的servlet 3.1方法。

HttpServletRequest#changeSessionId()

HttpServletRequest.changeSessionId()是servlet 3.1及更高版本中防止会话固定攻击的默认方法。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341

推荐阅读更多精彩内容