Spring Boot中Spring Security OAuth2的变化(相比XML配置)

在升级使用基于 Spring Boot 的 Spring Security OAuth2 后,相比于XML配置,除了所谓的“零配置”区别外,

在OAuth2的使用与流程中有以下几点变化

 

1. resource-id 只能配置一个(或不要);在XML配置时,可设置多个resource-id(详细请点此);但在Spring Boot中,

一个程序中只能配置唯一的一个resource-id (详细请点此)—— 个人觉得是因为一个微服务就是一资源(resource)吧。

 

2.ClientDetails中的 client_secret 值加密存储;使用的加密方式与Spring Security的密码加密方式一致;这是安全上

的一大提升,点赞。

 

 

https://gitee.com/shengzhao/spring-oauth-server

 

spring-oauth-server 2.0.0 发布,使用Spring-Boot2.0实现

经过一年多的时间后,我们发布了 spring-oauth-server 2.0.0版本.

使用Spring-Boot 2.0版本重构, 进入模块化,零配置时代. 更符合技术发展与实际需要.

相比之前的版本(1.0及之前版本), 更新如下:

1. 全新的 Spring-Boot风格

2.ClientDetails中的 client_secret 字段加密保存

3.密码加密方式由MD5变成 BCrypt

4.增加CSRF机制支持

5.resourceId变为可选(但建议使用固定的resourceId)

https://gitee.com/shengzhao/spring-oauth-server/tree/2.0.0/

Spring Security 5中 PasswordEncoder的使用

在最新的 Spring Security 5发布版本中, 出于安全性的考虑调整了PasswordEncoder的实现与使用策略.

1.以前常用的实现 StandardPasswordEncoder, MessageDigestPasswordEncoder, StandardPasswordEncoder 不再推荐使用, 全加上了@Deprecated ,并有具体的说明

1

推荐使用BCryptPasswordEncoder, Pbkdf2PasswordEncoder, SCryptPasswordEncoder等

 

2.增加 PasswordEncoderFactories 类提供一个静态方法 createDelegatingPasswordEncoder()方法, 使用委托方式创建PasswordEncoder的实现

2

在此方法的实现中,实际上使用了 BCryptPasswordEncoder 作为默认的实现(我想, 这也是Spring Security团队推荐使用的吧).

 

3.关于加密salt(盐值)的变化. 在之前的使用中, 一般在使用时自己指定salt值,一个配置示例如下:

3

而在新的使用中, salt的实现 将由各具体实现类去处理(如使用随机生成的值), 以 BCryptPasswordEncoder的实现说明

4

如图,在进行加密时, 使用随机生成的salt值或由指定的 strength, random去生成.

比如原密码为 admin, 分别进行两次 bcrypt加密的结果如下

$2a$10$OEaUDkvTlWY/BpoAL7f.H.X7Cz9x3OR3pfWv5wasidP4B7izvyRy6
$2a$10$BBFV5eyg4YoBLThOzi1bDO0WYDBCzcLq3ISokgzxCB/CM0YTXHrha

里面也有 salt 的作用.

 

 

以上为使用 Spring Security 5中 PasswordEncoder的变化总结, 希望对你有用.

当然, 更安全的加密可以使用基于Spring Security提供的类去进行扩展自己的PasswordEncoder实现

Java HeartBeat 2.0.0 发布,心跳检测应用服务器的Spring-Boot程序

Java HeartBeat 2.0.0版本已经发布, 使用Spring-Boot框架, 全新的”零配置”设计,向微服务化靠近,抛掉沉重的XML配置文件.Java HeartBeat 是心跳检测应用服务器(如 Tomcat,Jetty)的 Java Web 应用程序。

2.0.0版本主要更新如下:

1).使用 Spring-Boot 框架重构, 向微服务靠近
2).使用log4j2替换旧的log4j
3).更新登录页面样式,增加版本显示
4).单元测试使用Junit替换旧的TestNG
5).Sitemesh使用3.0版本替换2.0版本

HeartBeat 2.0.0版本访问地址: https://gitee.com/mkk/HeartBeat/tree/V-2.0.0/

https://gitee.com/mkk/HeartBeat

Spring Security中 salt 的最佳使用

salt, 盐, 用来做什么? 自己搜索下吧, 不解释这个基础的问题.

Spring Security中使用salt 有以下方式:

1.不使用 salt                       (强烈不推荐)

配置如下

1

使用 sha-256 加密

 

2.使用固定的salt 值          (不推荐)

配置如下

2

此处配置的固定值: my-salt

 

3.使用UserDetails中的一个属性值, 通过反射动态获取   (推荐)

配置如下

3

使用UserDetails中的username 属性的值为salt

 

4.自己实现 SaltSource.java 类,扩展性好           (推荐)

配置如下

4

使用扩展的 MySaltSource , 自定义实现,扩展性强

 

最佳使用实践

1. 使用UserDetails 的某一属性为salt的动态值 , 但这个属性不要与用户相关(如username), 比如定义一个 saltValue 属性, 每次创建时随机生成此值并存储,不修改.

2.扩展 SaltSource.java实现 , 比如使用两种加密算法去加密等.

 

另外

1. 对password的加密使用不可逆的算法实现, 如: SHA-XXX,  MD5 , 不能使用可逆的加密, 如: AES

2. password是敏感数据, 切不可记录到日志中, 保存在许多地方等.

Spring Security使用X509实现认证

在Spring Security的API文档中有一页专门介绍 集成X509进行认证的(http://docs.spring.io/spring-security/site/docs/3.0.x/reference/x509.html), 但是很不详细.

在实现认证之前先来说下X509,

X509是一种国际标准(具体为ITU-T X509),是一种通用的证书格式, 常用的文件后缀如 .p12, .pfx. (依据不同的CA厂商提供的有所区别)

一些概念,如 DN, 加密算法(alg), 证书有效期(validity)也是需要先了解清楚

而实际上X509是很多安全传输与认证的基础, 最常见的是SSL (https访问) 就是一具体实现

集成X509后的Spring Security会实现双向认证(HTTPS是单向认证, 即只有浏览器对服务器的, 而没有服务器对浏览器的).

Spring Security在整个过程中,其实只是使用了DN的属性值来获取用户名,然后去认证这个用户名是合法的即可(没有密码的验证, 因为双向证书已经是可信的).

— 意味着没有Spring Security X509也能工作

 

即整个集成大部的工作是在客户端与服务器中配置, 包括先获取证书, 安装证书(客户端), 将客户端证书导入到服务器配置中等.

具体的步骤下面这篇文章讲的很清楚, 请移步查阅

http://www.68idc.cn/help/buildlang/java/2014021668868.html (Spring Security 学习之X.509认证)

 

 

更多参考

Tomcat生成https+ssl双向证书认证
https://jingyan.baidu.com/article/0f5fb099f1f9566d8334ea38.html

 

若需要帮助请访问 https://gitee.com/mkk

Java HeartBeat 1.0.0 发布

在经历近一年的不知所措后(2016-08-15到2017-07-09), 更新了 HeartBeat 1.0.0 版本,Java HeartBeat是心跳检测应用服务器(如Tomcat,Jetty)的JAVA WEB应用程序。

1.0.0版本主要是功能完善与修复BUG, 主要内容如下:

1).添加更多监控时间,如2分钟,3分钟,5分钟,10分钟,半小时,1小时
2).Fix 设置多次失败后在提醒时的错误,以及恢复后的提醒
3).增加设置定期清理一段时间(默认为30天)前的监控日志记录,防止frequency_monitor_log表太大导致查询慢
4).修复未登录时不能查看到私有实例的日志
5).Fixed Issue #26 关于邮件发送次数的问题

 

HeartBeat 1.0.0版本访问地址: http://git.oschina.net/mkk/HeartBeat/tree/V-1.0.0/

http://git.oschina.net/mkk/HeartBeat

spring-oauth-server 如何扩展使用其他数据存储方式

spring-oauth-server项目默认提供了MYSQL数据库进行数据存储, 另一个branch: mongodb 使用了MongoDB进行数据存储.

但如果你想在使用时用其他的数据存储方式(如ORACLE,SQL SERVER, REDIS),该如何办呢? 以下给出一些思路, 希望能帮上你.

理论准备:

spring-oauth-server项目实际是一个基于Spring框架的, 而Spring的核心思想是什么——面向接口编程, 而面向接口编程带来的好处就是扩展性很强(不是一般的强), 以此为出发点来思考.

同时想想默认的spring-oauth-server使用MYSQL时有哪些数据进行了存储, 就寻找这些存储相关的类进行扩展.

具体实现:

(以mongodb 分支为例)

1.扩展接口TokenStore.java, 写自己的TokenStore实现类, 参见MongoTokenStore.java类. 同时在security.xml中配置tokenStore时使用自己扩展的类,如下图:

tokenStore

2.扩展接口ClientDetailsService.java,写自己的ClientDetailsService实现类, 参见MongoClientDetailsService.java类,同时在security.mxl中配置clientDetailsService时使用自己扩展的类,如下图:

clientDetailsService

3.扩展接口AuthorizationCodeServices.java,写自己的AuthorizationCodeServices实现类, 参见MongoAuthorizationCodeServices.java类,同时在security.xml中配置authorizationCodeServices时使用自己扩展的类,如下图:

authCode

 

OK, 在实现上面3个步骤后, 扩展实现数据存储方式就差不多了(当然,写一些辅助类是不错的,如MongoTokenStore实现时注入使用了AccessTokenRepository; 这能带来代码结构清晰,维护方便 ,扩展性强等好处), 以上的3个接口都有些抽象的或默认的实现类,如TokenStore默认时使用的实现类为InMemoryTokenStore.java, 借助强大的IDE工具去查看各个接口已有的实现类, 仿照或参考去扩展实现自己需要的实现类并配置即可, 比如可以继承一些已有的实现类进行覆盖扩展也是不错的主意.

 

编程之艺在于融会贯通,周而复始; 在于一种思想思考—面向期望编程!!!

 

spring-oauth-server 0.6 发布,OAuth2 与 Spring Security 安全应用整合

spring-oauth-server 0.6版本发布,该版本主要增加有缓存的支持, 具体的功能更新如下:

  • (150) – 修改OAUTH错误时返回JSON数据
  • (151) – 数据添加Ehcache缓存支持
  • (158) – 对配置,代码必要的地方添加注释,方便理解
  • 添加OIDC协议文档

OIDC是基于OAuth2的下一代身份认证授权协议,在0.6版本中添加了对OIDC1.0版本协议文档,同时在进行中文的翻译,具体请访问 https://andaily.com/blog/?p=440

spring-oauth-server 是一个整合OAuth2与Spring Security的安全应用项目,是从https://github.com/spring-projects/spring-security-oauth/tree/master/spring-security-oauth2扩展的符合实际项目需要的开源项目,可扩展为移动SSO解决方案.

0.6版本访问地址: http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.6/

 

正确处理spring-oauth-server中在验证失败或错误时的方式

在文章 https://andaily.com/blog/?p=97 中提到了OAUTH验证失败或错误时的处理办法, 但该方式是不完美的.

通过剖析代码发现,为什么在浏览器中会返回XML格式的数据, 而在使用类似HttpClient的请求时返回的数据格式为JSON,

其实所有的根源都在于请求header中的Accept的值所决定的,如果Accept不支持application/json, 那服务端肯定不会返回JSON格式的数据,

通过浏览器的开发者工具很容易追踪,如下图:

web_response_xml

 

从图中可以看出我们在请求时header中Accept的值为:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8; 服务器响应401

没有json格式的 media type, 但有xml的, 所以返回的数据格式不会是JSON的在浏览器请求时, 同时请注意 response header中的WWW-Authenticate.

 

相同的请求,如果我们换一种方式, 如Postman, 其结果返回的却是JSON格式的.如下图:

postman_response_json1

 

这也是因为请求时的header中Accept导致的, 看下图:

postman_response_json2

 

Postman在请求时的Header中设置了Content-Type: application/json; 同时也注意WWW-Authenticate.

 

综上分析, 你应该知道如何在请求时设定响应时的数据格式了吧. 方法如下:

1. 如果能指定Header中的Accept或Content-Type, 则指定为具体的数据类型或 media type  (一般用在非浏览器环境)

2.不管返回的数据体(response body)是XML还是JSON, 通过响应的header来处理, 如果响应码不是200, 则获取Header中WWW-Authenticate的值.

通过解析WWW-Authenticate的值来获取错误信息 (适用几乎所有环境)

 

 

http://git.oschina.net/shengzhao/spring-oauth-server