文档章节

为一个REST服务使用Spring Security的基本和摘要认证

Big_BoBo
 Big_BoBo
发布于 2014/01/16 16:37
字数 1532
阅读 14739
收藏 26

原创翻译自:http://www.baeldung.com/2011/11/20/basic-and-digest-authentication-for-a-restful-service-with-spring-security-3-1/

1. 简介

    这篇文章讨论的是如何在一个相同URI结构的REST API上使用基础和摘要式的认证。在一篇从前的文章里,我们讨论了另一种保护REST服务的方法----表单为基础的认证,但是基础的和摘要式的认证是另一个更自然的方式,也是更RESTful的一种。

2. 基础认证的配置

    表单为基础的认证不是RESTful服务的一个合适认证方式的主要原因是Spring Security将会使用Sessions -- 这当然是一个服务器的状态,所以REST服务是一种无状态的服务这一原则实际上是被违背了。

    我们将开始设置基础认证 -- 首先我们从主要的<http> security 元素中移除老的自定义入口和过滤器,

<http create-session="stateless">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />
 
   <http-basic />
</http>

    注意如何增加简单的一行配置<http-basic />来开启基础认证 -- 它是处理创建和装配BasicAuthenticationFilter BasicAuthenticationEntryPoint。

2.1. 满足无状态的约束 - 摆脱sessions

    RESTful风格一个主要的约束就是客户与服务器的通讯是完全无状态的(stateless),就像论文中写的:

    5.1.3 无状态

    我们接下来增加一条客户端-服务器交互的约束: 通讯必须是无状态的,在章节3.4.3中的无状态的 客户端-服务器风格里,每一次从客户端到服务器的请求必须包含所有必须的信息来理解此请求,并且不能使用任何存储在服务器中的内容。Session状态因此必须完整的保持在客户端上。

    服务器中的Session在Spring Security中是一个历史悠久的概念,想要完全的移除它现在看来是很困难的,特别是当配置命名空间时。然而,Spring Security 3.1为session的创建扩展了一个新的无状态的命名空间(namespace)选项,这可以有效地保证Spring的无session化。这个新选项的作用是在security filter chain相关的filters中完全移除所有的session,保证每一个请求都会进行身份认证。

3. 配置摘要式认证

    接着前边的配置继续,filter entry point 需要设置摘要式认证的定义beans。然后,digest entry point将会在后台覆盖<http-basic>创建的entry point。最后,自定义的digest filter将会织入到security filter chain,直接放置在基础认证过滤的后边。

<http create-session="stateless" entry-point-ref="digestEntryPoint">
   <intercept-url pattern="/api/admin/**" access="ROLE_ADMIN" />
 
   <http-basic />
   <custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>
 
<beans:bean id="digestFilter" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
   <beans:property name="userDetailsService" ref="userService" />
   <beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>
 
<beans:bean id="digestEntryPoint" class=
 "org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
   <beans:property name="realmName" value="Contacts Realm via Digest Authentication"/>
   <beans:property name="key" value="acegi" />
</beans:bean>
 
<authentication-manager>
   <authentication-provider>
      <user-service id="userService">
         <user name="eparaschiv" password="eparaschiv" authorities="ROLE_ADMIN" />
         <user name="user" password="user" authorities="ROLE_USER" />
      </user-service>
   </authentication-provider>
</authentication-manager>
    不幸的是,没有像配置基础认证使用<http-basic>一样的命名空间方式来配置摘要式认证。正因如此,必要的beans不得不被手工定义和装配到security 配置中。

4. 在一个RESTful服务中同时支持两种认证协议

    单独的基础认证和摘要认证可以很容易地被 Spring Security 3.x实现;它也支持在同一个RESTful服务中同时使用,在同一个URI中进行映射提升了配置和测试这个服务的复杂性。

4.1. 匿名请求

    在 security chain中同时使用基础和摘要认证的情况下,匿名请求的方式 --- 一种不包含任何认证凭据的请求 (Authorization HTTP header) --- 被Spring Security处理 --- 两种认证过滤会找不到任何凭据并继续执行过滤链。然后,我们会看到一个请求如果没有认证通过,一个AccessDeniedException 会被抛出并获取在ExceptionTranslationFilter中,跳转到摘要入口,提示客户端输入凭据。

    基础认证和摘要认证的功能是非常有限的,如果不能定义请求中认证凭据的类型他们会继续执行安全过滤链。所以 Spring Security可以非常灵活的在同一URI上配置多重认证协议配置。

    当一个请求包含正确的认证凭据时 - 基础的或者摘要的 - 协议都可以被正确的使用。然而,任何匿名的请求,客户端将会被提示摘要认证凭据。这事因为摘要入口被配置为主要的、单一的 Spring Security入口;所以,摘要认证可以被考虑为默认的认证入口。

4.2. 带认证凭据的请求

    基础认证定义一个带凭据的请求是通过Authorization中带“Basic”前缀的请求头。当处理这样一个请求时,凭据将会被解码到基础认证过滤器中并且请求将会被认证。类似的,一个带凭据的摘要请求使用的是带“Digest”前缀的Authorization 请求头。

5. 测试上面的场景

    测试将会消费REST服务,通过在基础/摘要认证后创建的一个新资源:


@Test
public void givenAuthenticatedByBasicAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().preemptive().basic( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );
 
   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
@Test
public void givenAuthenticatedByDigestAuth_whenAResourceIsCreated_then201IsReceived(){
   // Given
   // When
   Response response = given()
    .auth().digest( ADMIN_USERNAME, ADMIN_PASSWORD )
    .contentType( HttpConstants.MIME_JSON ).body( new Foo( randomAlphabetic( 6 ) ) )
    .post( paths.getFooURL() );
 
   // Then
   assertThat( response.getStatusCode(), is( 201 ) );
}
    注意这些测试优先增加凭据到请求中来使用基础认证,不论服务端是否以认证发起盘问。这保证了服务器不需要盘问客户端的凭据,因为如果它盘问了,盘问将会导致摘要的认证,以为这事默认的认证方式。


6. 结论

    这篇文章覆盖了为RESTful服务配置和实现基础认证和摘要认证,使用了大多数的Spring Security 3.0命名空间支持和一些 by Spring Security 3.1新增的新特性。

    查看完整的实现,请 check out the github project.

© 著作权归作者所有

共有 人打赏支持
Big_BoBo
粉丝 53
博文 54
码字总数 22137
作品 0
杭州
高级程序员
私信 提问
使用Spring Security开发基于表单的认证(一)

使用Spring Security开发基于表单的认证(一) SpringSecurity核心功能: 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) 使用springsecurity的默认安全机制: 访问接口时,会弹...

JS_HCX
04/29
0
0
SpringBoot+mybatis+springsecurity实现用户角色数据库管理

SpringSecurity是专门针对基于Spring项目的安全框架,充分利用了依赖注入和AOP来实现安全管控。在很多大型企业级系统中权限是最核心的部分,一个系统的好与坏全都在于权限管控是否灵活,是否...

ben4
2017/11/24
0
0
使用Spring Security开发基于表单的认证(二)

使用Spring Security开发基于表单的认证(二) 个性化用户认证流程 一、自定义登录页面 ①加页面:定义该页面hcx-signIn.html为登录页面: ②配授权 hcx-signIn.html: 注意,如果忘记配授权...

JS_HCX
04/30
0
0
【SpringSecurity】用户自定义认证

自定义用户认证逻辑 处理用户信息获取逻辑-UserDetailsService 用户信息被封装在一个接口里面的UserDetailsService,由SpringSecurity提供,如下: 该接口里面有一个loadUserByUsername方法,...

zlt995768025
05/13
0
0
Java for Web学习笔记(一四二)Spring security准备(3)初窥

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flowingflying/article/details/82865058 了解Spring Security的基本知识 完全J2EE的web container也能提供完...

恺风
09/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

node上的redis调用优化示例

Node.js读写数据到influxDB,目前已经有一个库node-influx, 这个库功能非常强大,但是我个人使用这个库的时候,遇到无法解决的问题。 使用curl都可以写数据到influxDB,但是用node-influx总是...

前端攻城老湿
9分钟前
1
0
The setting logImpl is not known

问题: org.apache.ibatis.builder.BuilderException: The setting logImpl is not known. Make sure you spelled it correctly (case sensitive). MyBatis 3.1.1 -jar还没有 logImpl 这个设......

晨猫
21分钟前
1
0
eslint一些规则

一、指定js文件不使用 ESLint 语法检查 1.整个文件范围内禁止规则出现警告 将/* eslint-disable */放置于文件最顶部 /* eslint-disable */alert('foo'); 2.在文件中临时禁止规则出现警告 ...

xiaoge2016
21分钟前
1
0
mac终端常用命令

ls ls,list的简写,列出目录的内容。 -a:显示隐藏文件 -l:以列表方式显示文件信息 -h:配合-l,显示更人性化 配合通配符使用 ls *.txt:显示所有以.txt结尾的文件 ls ?.txt:显示‘任意字符.tx...

xiaobai1315
23分钟前
1
0
java命令行读取配置,和加载jar的方式

--spring.profiles.active=t2,t3,xextest --spring.profiles.include=quartz-jp-Djava.ext.dirs=libs-Dspring.config.location=/data/apps/DBconfig -cp  "config/*"  start.sh......

经常把天聊死的胖子
34分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部