`

spring-security(二十二)基本认证和摘要认证

阅读更多
前言:
  在web应用中,非常流行以基本认证和摘要认证作为备选的认证机制。其中基本认证常用来对无状态的客户端进行认证,例如结合基于form的认证形式我们既能给用浏览器访问的用户提供认证也能给用web-service(restful)进行访问的用户提供认证。因为基本认证时用户名和密码都是以文本形式传递到服务端的,在安全级别高的应用中,基本认证要在传输过程中进行加密,例如采用https的形式。
一、基本认证
1.过滤器BasicAuthenticationFilter
和基本认证相关的逻辑主要在这个filter,当filter收到请求时按照如下逻辑执行
  • 从request的header中获取属性Authorization对应的数据,如果Authorization对应的value不是以【Basic 】开头,表示不是用basic形式认证的,跳过当前过滤器
  • 获取【Basic 】后的数据,用Base64进行解码,解码后以【:】进行分割,第一部分是用户名,第二部分是密码
  • 用上一步获取到的用户名和密码组装成UsernamePasswordAuthenticationToken,之后调用authenticationManager.authenticate方法进行认证
  • 如果认证成功将认证后组装好的Authentication对象放入SecurityContextHolder中并调用rememberMeServices.loginSuccess服务将用户名和密码编码后存入cookie中,执行记住用户功能
  • 如果认证失败,清除SecurityContextHolder中的认证对象,调用rememberMeServices.loginFail清除cookie信息,调用BasicAuthenticationEntryPoint的commence方法,设置response的头部,追加WWW-Authenticate信息,设置返回码为401
  • 例如
    HTTP/1.1 401 
    X-Content-Type-Options	nosniff
    X-XSS-Protection	1; mode=block
    Cache-Control	no-cache, no-store, max-age=0, must-revalidate
    Pragma	no-cache
    Expires	0
    X-Frame-Options	DENY
    Set-Cookie	JSESSIONID=493B4D42EC4A2D5AA85C7521288F54F9; Path=/; HttpOnly
    WWW-Authenticate	Basic realm="Realm"
    Content-Type	text/html;charset=ISO-8859-1
    Content-Language	zh-CN
    Content-Length	344
    Date	Tue, 06 Mar 2018 01:42:28 GMT
    Proxy-Connection	Keep-alive
    

    浏览器接收到信息后弹出框提示用户输入用户名和密码,之后浏览器将用户名和密码编码后发送到服务器,例如:
    GET /index.html HTTP/1.1
    Host	localhost:8080
    Cache-Control	max-age=0
    Authorization	Basic dXNlcjpwYXNzd29yZA==
    Upgrade-Insecure-Requests	1
    User-Agent	Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
    Accept	text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding	gzip, deflate, br
    Accept-Language	zh-CN,zh;q=0.9,en;q=0.8
    Cookie	JSESSIONID=493B4D42EC4A2D5AA85C7521288F54F9
    

    【dXNlcjpwYXNzd29yZA==】对应的值就是用户名和密码加密后的信息。
    认证过程如下:





    2.由上面的内容可以看到这种认证方式的认证逻辑非常简单,开发者也不用考虑登录页面如何显示,开发方式非常简便。但是采用这种认证方式请求头信息在传输过程中是明码传输的,采用的用户名密码加密方式为BASE-64,其解码过程非常简单,网络上很容易搜索到编解码的源码,所以很容易被破解,所以其认证技术并不是很安全一般都是在嵌入式设备上使用,实际应用中最好能结合tls技术对传递的信息进行加密,提高安全性。
    3.在spring boot应用中启用basic认证也很简单
    @Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    		.csrf()
    			.disable()
    		.authorizeRequests()
    			.anyRequest().authenticated()
    			.and()
    		.httpBasic();
    	}
    

    调用HttpSecurity的httpBasic()方法即可,具体这个方法是如何将BasicAuthenticationFilter追加到servletContext中的,可参考前面文章核心filter的讲解,此处不在展开。

    二、摘要认证
    1.摘要认证主要是为了解决基本认证中密码容易被破解的问题,通过将认证信息加密处理来提升安全性。

    在企业级应用开发中最好也不要考虑使用摘要认证,他只是相对基本认证的安全性有提升,但是还是有安全漏洞。最明显的问题是你必须将密码以明文、编码后、MD5处理中的一种形式保存下来,而这些算法都是可逆的算法,所以都是不安全的。相反我们应该采用单一方向的hash算法(bCrypt、PBKDF2、SCrypt)来保护我们的密码。只有更安全的认证方式在某些外部因素制约下不能采用时才考虑采用这种认证方式。

    2.摘要认证的核心是服务端产生的一个人不可理解的字符-“nonce”,采用如下算法生成
    base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
    expirationTime:   nonce过期的时间点,以毫秒为单位
    key:一个私有的key防止nonce被修改
    

    因为客户端在传递给服务器用户凭证时已经经过了加密,又不能恢复出来password信息,所以我们必须拿着原始密码经过相同的hash算法得出结果后再和客户端的结果进行比较,这就是为什么我们必须明文存储用户密码的原因

    3.DigestAuthenticationFilter
    和摘要认证相关的逻辑都在这个Filter中,主要的处理逻辑如下:
  • 从request的header中获取属性Authorization对应的数据,如果Authorization对应的value不是以【Digest 】开头,表示不是用basic形式认证的,跳过当前过滤器
  • 获取【Digest 】后的数据组装成DigestData
  • 利用生成nonce对应的key和realm对DigestData进行校验
  • 校验成功后调用userDetailsService.loadUserByUsername获取用户信息
  • 将获取到的用户的密码经过MD5算发获取到的结果和客户端传递过来的结果进行比对,一致则认证成功
  • 认证成功后将用户信息封装成Authentication,存入到SecurityContextHolder中
  • 如果上述步骤中的验证不成功,则认为认证失败,继续执行后续过滤器
  • 在后续过滤器中因为没有正常认证,最终ExceptionTranslationFilter会捕获到异常,调用DigestAuthenticationEntryPoint的commence方法,设置response header信息,返回客户端一个401,例如
    HTTP/1.1 401 
    X-Content-Type-Options	nosniff
    X-XSS-Protection	1; mode=block
    Cache-Control	no-cache, no-store, max-age=0, must-revalidate
    Pragma	no-cache
    Expires	0
    X-Frame-Options	DENY
    Set-Cookie	JSESSIONID=AE5A3F9F3ED75248B801954C58850A39; Path=/; HttpOnly
    WWW-Authenticate	Digest realm="security", qop="auth", nonce="MTUyMDMyMjk3NDIzOTpjOGZiMzYyY2MzNTQ1ZGQwN2UwNzE1YzE2YjExNWQwMg=="
    Content-Type	text/html;charset=ISO-8859-1
    Content-Language	zh-CN
    Content-Length	344
    Date	Tue, 06 Mar 2018 07:51:14 GMT
    Proxy-Connection	Keep-alive
    

    之后浏览器回弹框提示用户输入用户名和密码,之后浏览器将用户名和密码编码后发送到服务器
    GET /index.html HTTP/1.1
    Host	localhost:8080
    Cache-Control	max-age=0
    Authorization	Digest username="user", realm="security", nonce="MTUyMDMyMjk3NDIzOTpjOGZiMzYyY2MzNTQ1ZGQwN2UwNzE1YzE2YjExNWQwMg==", uri="/index.html", response="87007805d864a0f07f0bbf0e915fbe68", qop=auth, nc=00000001, cnonce="645f7f377909cc62"
    Upgrade-Insecure-Requests	1
    User-Agent	Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
    Accept	text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
    Accept-Encoding	gzip, deflate, br
    Accept-Language	zh-CN,zh;q=0.9,en;q=0.8
    Cookie	JSESSIONID=AE5A3F9F3ED75248B801954C58850A39
    


    认证的流程图和基本认证一样,唯一区别是Filter换成了DigestAuthenticationFilter,这里就不再画流程了。

    4.spring boot中配置degist认证方式
    @Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    		.csrf()
    			.disable()
    		.authorizeRequests()
    			.anyRequest().authenticated()
    			.and()
    		.exceptionHandling()
    			.authenticationEntryPoint(digestEntryPoint()).and()
    		.addFilter(digestFilter());
    	}
    
    	@Bean
    	public DigestAuthenticationEntryPoint digestEntryPoint() {
    		DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
    		entryPoint.setKey("chengf");
    		entryPoint.setRealmName("security");
    		return entryPoint;
    	}
    	
    	@Bean
    	public DigestAuthenticationFilter digestFilter() throws Exception {
    		DigestAuthenticationFilter digestFilter = new DigestAuthenticationFilter();
    		digestFilter.setAuthenticationEntryPoint(digestEntryPoint());
    		digestFilter.setUserDetailsService(userDetailsService());
    		return digestFilter;
    	}
    



    完整的示例代码参考:源码
    • 大小: 28.5 KB
    分享到:
    评论

    相关推荐

      spring-security-3.0.3 jar包( 含源码)

      它支持基本认证、表单登录、HTTP基本和摘要认证等,还可以自定义认证提供者。 2. **访问控制**:基于角色的访问控制(RBAC)是Spring Security的主要特性,它允许开发者定义权限规则,比如哪个角色可以访问哪个URL...

      spring-security-2.0.4.zip

      1. 身份验证:框架支持多种认证机制,如基于表单的登录、HTTP基本认证、摘要认证以及X.509证书等。用户信息通常存储在数据库中,可以通过自定义实现来对接其他身份验证源。 2. 授权:Spring Security提供了细粒度的...

      spring-security.zip

      要使用这些资源,你需要解压"spring-security.zip",查阅文档了解基本概念,然后通过示例代码学习如何在你的项目中集成和配置Spring Security。对于更高级的用法,如自定义认证和授权逻辑,可以深入研究源码和官方...

      spring-security-digest:spring-security 与摘要认证示例

      在这个特定的示例 "spring-security-digest" 中,我们关注的是摘要认证(Digest Authentication),这是一种比基本认证更安全的身份验证机制,因为它不直接在请求中传递明文密码。 摘要认证的基本原理是,服务器向...

      spring-security-3.0.1

      3.0.1版支持多种认证机制,包括基于表单的登录、HTTP基本认证、摘要认证等。`UserDetailsService`接口是获取用户信息的关键,你可以实现它来从数据库或其他数据源加载用户信息。 3. **Authorization**: 授权管理是...

      Spring Security-3.0.1中文官方文档(翻译版)

      实现摘要认证的过滤器。 **10. Remember-Me 认证** - **10.2 简单基于散列标记的方法** 通过存储一个散列值来实现“记住我”的功能。 - **10.3 持久化标记方法** 使用数据库或文件系统来持久化“记住我”的信息...

      spring-ws-security-soap-example:显示如何在Spring中设置安全的SOAP Web服务的示例

      Spring Web Services WS-Security示例 设置各种协议的样本 SOAP Web服务。 支持WS-Security的两种实现,即和 。 对于每种认证方法,每种认证方法都有一个不同的终结点: 不安全。 普通密码。 摘要密码。 签名...

      spring-security-3.1.1的jar包与文档

      Spring Security提供了全面的安全解决方案,包括用户认证、权限控制、会话管理以及对Web应用和基于方法的安全性支持。 在3.1.1版本中,Spring Security的核心功能包括: 1. **身份验证**:Spring Security提供了一...

      spring-security-examples

      Spring Security 提供了多种认证方式,包括基于表单的认证、HTTP基本认证、HTTP摘要认证等。在"spring-security-examples"中,你可以看到如何配置和实现这些认证机制,以及如何自定义AuthenticationProvider来处理...

      spring security 参考手册中文版

      6.2.3表单和基本登录选项 52 设置默认的登录目的地 54 6.2.4注销处理 54 6.2.5使用其他身份验证提供程序 55 添加密码编码器 56 6.3高级Web功能 56 6.3.1记得我认证 56 6.3.2添加HTTP / HTTPS通道安全 57 6.3.3会话...

      Spring3_权威开发指南 Spring3Security-3.0.1中文官方文档

      此外,还涉及了CSRF(跨站请求伪造)防护、记住我功能、HTTP基本认证和摘要认证、过滤器链的配置,以及与OAuth2的集成等。Spring Security还提供了对HTTPS的支持,以增强应用的通信安全性。 这两份资料结合使用,...

      springsecurity.pdf

      - **表单和基本登录选项**:可以自定义登录表单的样式和行为,同时支持 HTTP 基本认证。 - **设置默认的登录后目的地**:可以通过 `<form-login>` 元素的 `default-target-url` 属性来指定用户登录成功后的默认跳转...

      Spring Security 教程(Spring Security Tutorial)1

      Spring Security 提供了多种摘要认证的实现,包括 MD5、SHA 等算法。 10. **摘要认证的密码加密**: - 密码通常需要加密存储,Spring Security 提供了通用的密码加密机制,如 BCrypt 或 PBKDF2,这些算法能提供...

      SPRING_SECURITY_THIRD_EDITION

      Spring Security提供了对HTTP基本认证、摘要认证以及OAuth2认证等多种认证机制的支持。 除此之外,该书也着重讲解了在微服务架构下使用Spring Security。微服务架构是一种将单一应用程序作为一套小服务开发的方法,...

      SpringSecurity 3.0.1.RELEASE.CHM

      表单和基本登录选项 2.2.3. 使用其他认证提供器 2.2.3.1. 添加一个密码编码器 2.3. 高级web特性 2.3.1. Remember-Me认证 2.3.2. 添加HTTP/HTTPS信道安全 2.3.3. 会话管理 2.3.3.1. 检测超时 2.3.3.2. 同步...

      spring security 3 中文教程

      Spring Security通过强大的认证和授权机制,实现了对用户访问权限的精细控制。 #### 认证机制 Spring Security支持多种认证方式,包括但不限于: - **HTTP BASIC**:基于IEFT RFC标准的HTTP头验证,是最常见的...

      acegi-security-resin-0.8.3.jar.zip

      1. **用户身份验证**:Acegi支持多种认证方式,包括基于表单的登录、HTTP基本认证、摘要认证以及自定义认证策略。 2. **授权管理**:你可以通过Acegi定义哪些用户或角色可以访问哪些资源,这可以通过配置XML文件或...

      2016 page220 Spring Security Essentials - Nanda Nachimuthu.pdf )

      认证是识别用户身份的过程,Spring Security为Java应用程序提供了一种安全认证机制,支持多种认证方式,包括但不限于表单登录、HTTP基本认证、摘要认证等。此外,Spring Security还能够集成OAuth和LDAP等外部认证...

      spring security 安全权限管理手册

      如果配置正确,Spring Security 将拦截请求,并根据定义的安全规则执行认证和授权操作。 --- ##### 第2章:使用数据库管理用户权限 **2.1 修改配置文件** 当应用需要处理大量的用户和权限时,通常会选择将用户...

      spring security 中文指南

      Spring Security 的核心功能分为认证和授权两部分。认证是确认用户身份的过程,而授权则涉及确定用户是否可以执行特定操作。这两个概念是安全领域的基础,Spring Security 支持多种认证机制,包括: - HTTP 基本...

    Global site tag (gtag.js) - Google Analytics