具有Stormpath和Spring Boot的OAuth 2.0令牌管理

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

OAuth 2.0令牌管理经常被误解并且难以正确实施。 幸运的是,借助Stormpath的SDK和集成,我们使令牌管理变得轻松,有趣。 这个20分钟的教程将向您展示如何使用Stormpath的Spring Boot和Spring Security集成来实现令牌管理。

虽然Spring Security 确实内置了OAuth 2.0支持,但是Spring Boot中没有本机令牌管理支持,并且使用OAuth协议已知会导致荨麻疹,冷汗和长时间的“面部办公桌”自发爆发。

face_desk

Stormpath的Spring Boot集成支持两个OAuth流: grant_type=passwordgrant_type=refresh_token 。 密码授予类型允许您传递用户名和密码,并获取访问令牌和刷新令牌。 刷新令牌授予类型允许您传递刷新令牌并获取新的访问令牌。

它们都可以通过单个端点/oauth/token访问,该端点可通过Stormpath集成直接使用。 所以,不要害怕! Stormpath的令牌管理负责所有繁重的工作。 您只需要使用下面讨论的一些基本规则来创建HTTP请求。

本教程的资源

到本文结束时,您将拥有将用户名和密码交换为一组令牌所需要的一切,这些令牌使用户可以访问应用程序中的受限资源。 您还可以刷新和撤消令牌,以更好地控制用户访问您的应用程序的方式以及他们保持登录状态的时间。

支持这篇文章的代码在这里

您可以在以下位置查看运行中的示例: https//jquery-spa.herokuapp.com (由于Heroku 睡眠策略,您可能需要等待几秒钟才能使应用程序最初响应),然后可以将其部署到现在使用下面的按钮使用Heroku帐户。

纽扣

虽然令牌管理通常是幕后事务,但此示例使用SPA或单页应用程序。 为了使示例简单(并且与Javascript框架无关),所有调用均使用jQuery的ajax功能进行。

现代令牌管理–访问和刷新令牌

在支持OAuth 2.0令牌管理的现代应用程序中,用户会话通常具有一个具有较短到期时间的访问令牌和一个具有较长到期时间的刷新令牌。 当访问令牌过期时,应用程序将使用刷新令牌来获取新的访问令牌。 重复此过程,直到刷新令牌过期。 此时,用户将需要再次登录该应用程序。

要深入了解OAuth令牌及其工作原理,请查看我的同事Randall的帖子,其中详细探讨了OAuth

JSON Web令牌(JWT)安全PSA

OAuth 2.0规范未指定特定的令牌格式,因此Stormpath使用JWT来表示访问令牌和刷新令牌。 JWT已将其他信息编码到其中,更重要的是,它们已被加密签名以提供确凿的证据证明令牌未被篡改。

Stormpath访问令牌还提供了重要的附加安全层–它们始终包含对关联的刷新令牌的引用。 该参考文献是由代码rti标识的权利要求。 这是Stormpath确保它是用于访问受保护资源的访问令牌而不是刷新令牌的一种方式。 OAuth 2.0的其他实现(无意间)允许刷新令牌充当访问令牌,从而为用户提供了应有的更长访问时间。 我们对此保持警惕。

如果您想了解有关JWT以及如何安全使用JWT的更多信息,请查看有关如何正确使用JWT使用JWT 构建安全用户界面以及将JWT 存储在何处的文章

好的,所有这些都让我们开始吧!

Spring安全配置

在以下各节中,我们将通过对Spring Boot应用程序中的后端/oauth/token端点进行的jQuery调用来探讨示例应用程序。

在开始之前,让我们看一下该示例应用程序的Spring Security配置:

@Configuration
public class SpringSecurityWebAppConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.apply(stormpath()).and()
            .authorizeRequests()
            .antMatchers("/").permitAll()
            .antMatchers("/decode").permitAll()
            .antMatchers("/static/**").permitAll();
    }
}

Stormpath的Spring Security集成遵循Spring Security的默认访问配置,即所有路径均被锁定。

在以上配置中,我们允许未经授权的访问//decode以及/static任何路径。 通过下面的示例,我们将看到这一点。

让我们获取一些代币

在我们的SPA示例中,有两个主要的静态文件: home.htmlstatic/js/token-management-guided-tour.js

home.htmlThymeleaf模板,其中加载static/js/token-management-guided-tour.js Javascript文件。

这是home.html不同部分的视图:

首页1

它分为7个步骤,应用程序将引导您完成示例“导游”样式。

第一步是传递电子邮件和密码,然后取回访问和刷新令牌。 让我们看看实际情况。

用电子邮件和密码登录

这是jQuery代码,用于处理对/oauth/token端点的初始请求(为简便起见,省略了errorcomplete功能):

$('#login-form').submit(function (e) {
 
    var theForm = $('#login-form');
 
    $.ajax({
        type: 'post',
        url: '/oauth/token',
        data: theForm.serialize(),
        success: function (data) {
            accessToken = data.access_token;
            refreshToken = data.refresh_token;
            var accessTokenParts = accessToken.split('.');
            $.each(['header', 'payload', 'signature'], function (index, value) {
                $('#access-token-' + value).html(accessTokenParts[index]);
            });
            $('#login-error').hide();
            showOnlyDiv('access-token-div');
        }
    });
 
    e.preventDefault();
});

第3行为我们提供了该表格的句柄。

根据OAuth规范,该方法将为POSTContent-Typeapplication/x-www-form-urlencoded (这是jQuery的$.ajax调用的默认设置)。 传递给/oauth/token的数据将如下所示:

grant_type=password&username=<username>&password=<password>

这是第8行调用theForm.serialize()的结果。

从第9行开始的成功处理程序将access_tokenrefresh_token存储在局部变量中。 它还以JWT的可视表示形式在浏览器中显示access_token的各个部分(标头,有效负载和签名):

access_token

注意:如屏幕截图所示,示例应用程序仅用于演示目的。 在“现实生活”中,您不想在浏览器中显示访问令牌,并且希望使用最佳实践在客户端应用程序中存储令牌。 我们在这里有关于这些最佳实践的精彩文章。

Stormpath访问令牌的剖析

在示例应用程序中,如果单击“ Decode按钮,您将看到类似以下内容:

已解码

这显示了JWT的标头和有效负载部分,它们是访问令牌。 要了解我们如何解码访问令牌,我们需要看一下示例应用程序中APIController中的decode方法:

@RequestMapping("/decode")
public Jws<Claims> decode(@RequestParam String token) throws UnsupportedEncodingException {
 
    Jws<Claims> claims = Jwts.parser()
        .setSigningKey(client.getApiKey().getSecret().getBytes("UTF-8"))
        .parseClaimsJws(token);
 
    return claims;
}

该方法将JWT(在本例中为我们的访问令牌)作为参数,并使用JJWT库解析声明。 它还将验证JWT签名在解析过程中是否有效。 为此,它使用了Stormpath Client的机密,该机密最初是用来创建JWT的。

最后,该方法返回Jws<Claims>对象。 这是Spring Boot的自动Jackson JSON映射器启动并将该对象转换为JSON的地方。 这是原始响应的样子:

{
    "header": {
        "kid": "R92SBHJC1U4DAIMGQ3MHOGVMX",
        "alg": "HS256"
    },
    "body": {
        "jti": "6UBPQ975cDDiz8ckHqWIZF",
        "iat": 1456242057,
        "iss": "https://api.stormpath.com/v1/applications/2nBCvauLgETX8wO0VvS9mQ",
        "sub": "https://api.stormpath.com/v1/accounts/49CK1VvY2jQwUBH7UnP5zC",
        "exp": 1456245657,
        "rti": "6UBPQ5n0hcukMJWt5af1xB"
    },
    "signature": "Pm30FjdXOmx_fMGhfku85Z9xc6qE-EZgKHI4mV46KO8"
}

请注意,已解码JWT的body (有效负载)在sub (主题)声明中包括对Stormpath帐户的引用。 访问受限资源时将使用该帐户,我们将在后面看到。

使用访问令牌

解码访问令牌后,本示例应用程序的导览中的下一步是使用该访问令牌来访问受限资源。 这是完成此任务的jQuery代码:

$('#restricted').click(function () {
 
    $('#account-info-table tbody').empty();
    $.ajax({
        type: 'get',
        url: '/restricted',
        success: function (data) {
            var newRowContent = '<tr><td>' + data.fullName + '</td><td>' + data.email + '</td></tr>';
            $('#account-info-table tbody').append(newRowContent);
            showOnlyDiv('account-info-div');
        }
    })
});

您可能想知道上述代码中的身份验证在哪里。 登录时,已按照上述步骤在浏览器中设置了Cookies。如果您在浏览器中查看检查器,则会看到access_token一直传递到请求到/restricted端点。 在单独的浏览器会话中,您可以尝试点击: http://localhost:8080/restricted 。 您将被重定向到/login 。 这是我们的Spring Security配置的功能。 /restricted路径不是我们在Spring Security配置中明确允许的路径之一,因此,必须对请求进行身份验证。 为了了解/restricted的响应,让我们看一下APIController中的restricted方法:

@RequestMapping("/restricted")
public AccountInfo restricted(HttpServletRequest req) {
    Account account = AccountResolver.INSTANCE.getAccount(req);
    return new AccountInfo(account.getFullName(), account.getEmail());
}

这只是返回一个AccountInfo模型对象,该对象具有经过身份验证的用户的全名和电子邮件地址。 在示例应用程序中定义的AccountInfo对象可以通过我们在上面看到的相同的自动Spring Boot映射器过程轻松转换为JSON。

上面的jQuery success函数显示从请求返回到/restricted的Account信息。

令牌管理:令人耳目一新!

我们旅程的下一步是使用刷新令牌来获取新的访问令牌。 在典型的移动应用程序中,用户可能不知道以下情况:

  1. 当前访问令牌已过期
  2. 用户尝试使用(过期的)访问令牌访问应用程序的受限部分
  3. 该应用程序收到401 (未经授权)的HTTP响应代码
  4. 应用程序使用刷新令牌来获取新的访问令牌
  5. 应用程序尝试使用新的访问令牌访问应用程序的受限部分
  6. 用户无需再次登录即可查看该请求的结果

注意:如果刷新令牌已过期,则应用程序的用户将需要在步骤4再次登录。

Stormpath在管理控制台中提供了OAuth策略,以设置访问令牌和刷新令牌的到期时间。

看看OAuth政策

这是在Stormpath管理控制台中的OAuth策略:

oauth_policy

访问令牌的默认生存时间为1小时,而刷新令牌的默认TTL为60天。

刷新访问令牌

当您在示例应用程序中单击“ Refresh the Access Token按钮时,您将收到如下响应:

刷新

这将显示在刷新过程中检索到的新访问令牌。 为了了解发生了什么,我们回到jQuery代码(为简便起见,省略了成功处理程序):

$('#refresh').click(function () {
 
    $.ajax({
        type: 'post',
        url: '/oauth/token',
        data: 'grant_type=refresh_token&refresh_token=' + refreshToken,
        success: function (data) {
        }
    })
});

再次,我们对/oauth/token端点进行HTTP POST 。 与grant_type=password流不同,在这种情况下,我们使用的是grant_type=refresh_token ,并且传入的是之前保存的Refresh Token。

来自此ajax调用的响应是一个新的访问令牌,该令牌随后在浏览器中的旧访问令牌下方显示。

将代币踢到路边

我们的令牌管理游戏的最后一部分是撤销访问和刷新令牌。 这是通过点击(内置) /logout端点(将访问令牌提供为Bearer令牌)来实现的,就像我们之前访问受限资源时所做的那样。 让我们看一下完成此任务的jQuery代码:

$('#revoke').click(function () {
 
    $.ajax({
        type: 'post',
        url: '/logout',
        success: function () {
            showOnlyDiv('revoke-div');
        }
    })
});

我们正在向/logout发送HTTP POST请求。 此时,将删除包含access_tokenrefresh_token的cookie,并在Stormpath后端撤消令牌。 这是在后台自动处理的。

该示例应用程序尝试再次点击/restricted路径。 结果看起来像这样:

失败

结果表明,尝试使用已删除的访问令牌将无效。

综上所述

Stormpath的Spring Boot集成中提供了开箱即用的/oauth/token端点,可启用现代令牌管理系统的所有功能。

在本文中,我们介绍了什么是访问令牌和刷新令牌,以及如何获取,使用,刷新和吊销它们。

您可以在以下位置查看本文中使用的示例应用程序: https : //jquery-spa.herokuapp.com,或者您可以使用下面的按钮将应用程序部署到您自己的Heroku帐户。

纽扣

建筑物身份管理,包括身份验证和授权? 尝试Stormpath! 我们的REST API和强大的Java SDK支持可以消除您的安全风险,并且可以在几分钟内实现。 注册 ,再也不会建立auth了!

立即注册按钮

翻译自: https://www.javacodegeeks.com/2016/11/oauth-2-0-token-management-stormpath-spring-boot.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值