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/

MyOIDC – 基于OIDC协议的开源项目

在之前的博客文章中, 曾不止一次介绍了OIDC协议及相关知识(详细访问: https://andaily.com/blog/?s=OIDC)

现在,开始一个新的开源项目: MyOIDC (https://git.oschina.net/mkk/MyOIDC), 将其相关的知识与实现给代码化,

我们将着重提供比OAuth2实现更好,更安全的认证与授权 安全框架实现.

 

顺便传播OIDC, 使用OIDC, 拥抱OIDC…

欢迎你的关注与支持…

 

https://git.oschina.net/mkk/MyOIDC

openid

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/

 

oauth2-shiro 0.2版本发布

oauth2-shiro 0.2版本正式发布, 在7月完成开发工作,但由于当时发布 http://git.oschina.net/mkk/oauth2-shiro-redis 项目竟然给忘记了. 该版本主要更新如下

1.更新首页UI, 参照spring-oauth-server

2.Add client details overview

3.Add client details testing

4.user add/edit, overview

5.添加API使用说明, 举例各个场景

6.发布到测试服务器

7.resources模块更新UI说明

 

从0.2版本开始可在线测试,测试地址分别为:

authz: https://andaily.com/authz/

resources:https://andaily.com/rs/

0.2版本访问地址: http://git.oschina.net/mkk/oauth2-shiro/tree/0.2/

oauth2-shiro 整合OLTU与SHIRO, 提供一个轻量的OAUTH2应用框架.

grant_type=authorization_code 中 redirect_uri的代码实现参考

OAuth2中grant_type=authorization_code时, 需要填写redirect_uri, 而该uri将如何处理与实现呢, 在此提供具体的讲解与实现参考

redirect_uri在注册ClientDetails时需要提供(当grant_type包含authorization_code时), 且在发起OAUTH2流程时需要在参数中传递redirec_uri, 这两处的值必须一致.

 

在业务中, redirect_uri代码实现主要用于接收返回的code值, 校验state是否合法, 以及通过code换取accessToken操作.

在 spring-oauth-client 项目的 AuthorizationCodeController.java 类中, authorization_code_callback 方法实现了以上的逻辑, 在具体实现是可参考该方法的实现, 代码如下:

@RequestMapping(value = "authorization_code_callback")
public String authorizationCodeCallback(AuthCallbackDto callbackDto, HttpServletRequest request, Model model) throws Exception {

    if (callbackDto.error()) {
        //Server response error
        model.addAttribute("message", callbackDto.getError_description());
        model.addAttribute("error", callbackDto.getError());
        return "redirect:oauth_error";
    } else if (correctState(callbackDto, request)) {
        //Go to retrieve access_token form
        AuthAccessTokenDto accessTokenDto = oauthService.createAuthAccessTokenDto(callbackDto);
        model.addAttribute("accessTokenDto", accessTokenDto);
        model.addAttribute("host", host);
        return "code_access_token";
    } else {
        //illegal state
        model.addAttribute("message", "Illegal \"state\": " + callbackDto.getState());
        model.addAttribute("error", "Invalid state");
        return "redirect:oauth_error";
    }

}

 

这里实现首先检查服务端是否返回error信息,

然后判断state是否正确, 若正确则显示一个页面, 并在code_access_token方法中(同一个类中)使用 httpclient 发起请求(grant_type=authorization_code)通过 code换取access_token.

其它情况则显示error信息.

 

http://git.oschina.net/mkk/spring-oauth-client

spring-oauth-server中添加 resource 的配置

resource,资源, resource-id资源ID, 在spring-oauth-server中添加 client details时有两个resource可以选择(mobile-resource, unity-resource); 这些resource-id从哪来的呢? 如果我需要添加自己的resource将如何办呢, 请继续向下看.

resource用于将系统提供的各类资源进行分组管理,每一个resource对应一个resource-id, 而一个client details至少要有一个resource-id(对应OauthClientDetails.java中的resourceIds字段).

在spring-oauth-server的security.xml配置文件的70行左右, 你会看到两行配置,如下:

<!--unity resource server filter-->
<oauth2:resource-server id="unityResourceServer" resource-id="unity-resource" token-services-ref="tokenServices"/>

<!--mobile resource server filter-->
<oauth2:resource-server id="mobileResourceServer" resource-id="mobile-resource" token-services-ref="tokenServices"/>

这儿就是配置resource的地方, 看见里面的两个resource-id值.

在这配置往上, 能看见两个<http>的配置, 一个的pattern为/m/**, 另一个为/unity/**, 这就是资源与Spring Security整合后的配置, 注意每个<http>配置里的 ROLE_UNITY与ROLE_MOBILE, 这对应Spring Security的权限; 截图如下:

resource-config

有了以上基础, 及下看我们要添加一个自己的resource, 假设resource-id = myResource, url pattern为/my/api/**, 权限为ROLE_MY_RESOURCE, scope为 read; 其配置如下:

1.添加<oauth2:resource-server> , resource-id=myResource, 如下:

<oauth2:resource-server id="myResourceServer" resource-id="myResource" token-services-ref="tokenServices"/>

注意, id值需要唯一
2.添加<http>配置, 如下:

<http pattern="/my/api/**" create-session="never" entry-point-ref="oauth2AuthenticationEntryPoint"
      access-decision-manager-ref="oauth2AccessDecisionManager" use-expressions="false">
    <anonymous enabled="false"/>

    <intercept-url pattern="/my/api/**" access="ROLE_MY_RESOURCE,SCOPE_READ"/>

    <custom-filter ref="myResourceServer" before="PRE_AUTH_FILTER"/>
    <access-denied-handler ref="oauth2AccessDeniedHandler"/>
    <csrf disabled="true"/>
</http>

说明: 一个<resource-server>可以配置多个<http>, 使用不同的url pattern

OK, 配置完成, 新增resource: myResource; 这时候, 所有以/my/api/** 开头的URL请求都将受到 OAUTH2的保护, 及下来在业务中创建client details, 记得把resourceIds设置为myResource,且要有ROLE_MY_RESOURCE的权限.

 

spring-oauth-server

传递access_token参数的正确方式

在OAuth中, access_token参数的传递如何才能更安全呢? 不知你有没有具体去研究过, 在此总结传递access_token的正确方式,

(所谓正确方式是指传递方式更安全, 更隐匿, 更不容易被网络拦截,网络攻击的方式)

 

在 spring-oauth-server 与 oauth2-shiro 中均支持以下提到的传递access_token的方式.

 

1. 通过Header传递 access_token; [推荐]

在请求URL的Header中, 添加header -> Authorization: bearer access_token,  示例代码(Java):

postHandler.addHeader("Authorization", "bearer 0fe12a74-e613-4d1b-9785-f96847bad346");

一般在代码中使用httpclient或URLConnection来实现,如Android, IOS客户端, 不适用于浏览器传递access_token

2.若请求URL使用POST方式提交, 将access_token放在请求body中而不是拼接在URL上, 示例代码(HTML):

<form action="db_table_description" method="post">
    <input type="hidden" name="access_token" value="0fe12a74-e613-4d1b-9785-f96847bad346"/>
    <input type="text" name="username"/>
    <button type="submit">Submit</button>
</form>

3.最后的选择, 通过URL拼接参数access_token, 示例代码:

http://monkeyk.com/oauth_test?access_token=0fe12a74-e613-4d1b-9785-f96847bad346

一般使用在GET请求, POST等其他请求方式也支持

以上三种方式, 优先选择第一,第二种, 少用第三种方式.这些方式都是基于HTTP请求下所采用的.
更安全的传递access_token的方式是启用HTTPS连接,保证网络传输安全.