身份验证 – 在Jersey Jax-rs Web服务上启用OAuth1支持

我想在我的restful Web服务上启用OAuth1 Provider支持.泽西支持这一点,如 Jersey OAuth1 Provider support所述.
我一直试图将其注册为:

public ApplicationConfig(){
    super();
    addRestResourceClasses(getMyResourceClasses());                 
    register(new OAuth1ServerFeature(new DefaultOAuth1Provider(),"/oauth/access_token","/oauth/request_token"));
}

但是,当我注册OAuth1ServerFeature时,在尝试访问我的资源时会得到404.
似乎无法找到任何实施泽西oauth支持的示例/教程!

是否有一个简单的组件可以插入我的jax-rs服务以启用oauth支持?

解决方法

我意识到这个线程有点老了 – 但是自己刚刚开始工作,我感觉回复是有序的!有了时间,我甚至可以创建一个更全面的博客文章.请注意 – 这不是一个简短的答案!

关于在泽西岛使用OAuth1服务器(又名提供商)功能的信息绝对缺乏示例 – 我不记得一个技术主题,揭示了如此少有用的谷歌信息.我几乎继续寻找另一种解决方案,因为它让我想到也许它不起作用.但是,有了一些毅力,我可以说它不仅可以使用,而且似乎运作得相当好.当然,如果您已经使用Jersey作为REST API – 您不需要任何额外的库.

我不是OAuth1专家 – 我强烈建议那些尝试此操作的人阅读.我也在这里假设你有泽西岛工作,理解像ContainerRequestFilters这样的东西,并且还有一些内部手段来授权用户.

我的示例还使用了优秀的JAX-RS OSGi连接器 – 唯一真正的区别是,我们使用OSGi捆绑上下文通过OSGI服务注册OAuth1功能,常规Jersey用户需要通过其正常的Application / Server配置模型进行配置.

初始化

您必须创建OAuth1功能 – 并为其提供提供程序:

DefaultOAuth1Provider oap = new DefaultOAuth1Provider();
Feature oaFeature = new OAuth1ServerFeature(oap,"oauth1/request_token","oauth1/access_token");

别忘了在泽西岛注册oaFeature!

DefaultOAuth1Provider完全基于内存 – 这对我们来说很好.许多人希望持久访问令牌以便在服务器重启时使用,这将需要扩展的子类(或干净的实现)

添加您的消费者密钥和秘密

我花了一段时间才意识到消费者不是用户而是客户,即应用程序.如果您没有为希望连接的每个消费者(也称为客户端应用程序)注册密钥和机密,则Jersey实施将不起作用

oap.registerConsumer("some-owner-id","abcdef","123456",new MultivaluedHashMap<String,String> ());

你显然永远不会硬编码这些,并进一步使用某种形式的安全存储为秘密(参数3).

如果你不添加这些,你将不会得到任何进一步.

OAuth协议第1步 – 获取请求令牌

在这个阶段,您已准备好客户端获取请求令牌 – 这里有一个perfectly good example on GitHub.

ConsumerCredentials consumerCredentials = new ConsumerCredentials("abcdef","123456");

//TODO - user proper client builder with real location + any ssl context
OAuth1AuthorizationFlow authFlow = OAuth1ClientSupport.builder(consumerCredentials)
            .authorizationFlow(
                    "http://myhost:8080/myapi/oauth1/request_token","http://myhost:8080/myapi/oauth1/access_token","http://myhost:8080/myapi/oauth1/authorize")
            .build();
String authorizationUri = authFlow.start();
System.out.println("Auth URI: " + authorizationUri);

显然,您将更改URL以指向您的服务器 – 至关重要的是 – 客户端需要使用您在服务器中注册的相同Conumer密钥和密钥.

您将获得一个带有oauth_token字符串的响应,例如

http://myhost:8080/myapi/oauth/authorize?oauth_token=a1ec37598da
b47f6b9d770b1b23a5f99

OAuth协议第2步 – 授权用户

正如您将在任何文章中读到的那样,实际的用户授权超出了OAuth1的范围 – 在此阶段,您必须调用您的服务器身份验证过程.

然而!!!!不在OAuth1范围之外的是您的服务器在用户成功授权时需要执行的操作.您必须告诉DefaultOAuth1Provider有关成功的身份验证:

// Dummy code - make out like we're auth'd
Set<String> dummyRoles = new HashSet<> (Arrays.asList( new String[] { "my-role-1","my-role-2" }));
DefaultOAuth1Provider.Token tok1 = getRequestToken("a1ec37598da
b47f6b9d770b1b23a5f99");
String verifier = authorizeToken(tok1,new Principal()
            {
                public String getName()
                {
                    return "my-user";
                }
            },dummyRoles);
System.out.println("***** verifier: " + verifier);

请注意,请求令牌字符串是来自步骤1的字符串.显然,真正的实现将为授权用户传递真实的Principal和一组角色.

此外,当然,打印验证器并没有多大用处 – 您需要以某种方式将其返回给客户端,可以通过独立通道或可能作为auth响应中的标头 – 可能需要加密增加保护.

OAuth协议步骤3 – 交换请求令牌以获取访问令牌

一旦客户端接收到或者手动输入了验证者,它就可以完成该过程并交换请求令牌以获取访问令牌,例如

String verifier = System.console().readLine("%s","Verifier: ");
final AccessToken accessToken = authFlow.finish(verifier);        
System.out.println("Access token: " + accessToken.getToken());

同样,这不是一个现实的例子 – 但它显示了这个过程.

如果您的OAuth1Provider将访问令牌保存到服务器上的某个持久性存储,则可以在未来的会话中重复使用此处返回的任何访问令牌,而无需执行上述所有步骤.

就是这样 – 您只需要确保客户端在此过程中创建的每个请求都使用该访问令牌.

相关文章

HTML代码中要想改变字体颜色,常常需要使用CSS样式表。CSS是...
HTML代码如何让字体盖住图片呢?需要使用CSS的position属性及...
HTML代码字体设置 在HTML中,我们可以使用标签来设置网页中的...
在网页设计中,HTML代码的字体和字号选择是非常重要的一个环...
HTML(Hypertext Markup Language,超文本标记语言)是一种用...
外链是指在一个网页中添加一个指向其他网站的链接,用户可以...