对于那些不熟悉的人,ApacheShiro(一种Java安全框架)执行授权,身份验证和会话管理(以及许多其他功能),以帮助构建更安全的应用程序。
这篇文章将向您展示如何使用JAX-RS来构建一个简单的JavaREST应用程序。JAX-RS是一组接口,因此您需要选择实现。在本文中,我们将使用Jersey—但是您可以使用自己喜欢的任何实现,而且这些API都不是Jersey特有的。
在OAuth 2.0中,REST服务通常是资源服务器。简单来说,它们使用在Authorization HTTP标头中发送的访问令牌进行身份验证,格式为Authorization:Bearer <access-token>。
Authorization
Authorization:Bearer <access-token>
创建一个新的JAX-RS项目 有几种创建新的基于Maven的项目的方法。我通常使用我的IDE,但是您也可以在命令行上生成一个。无论采用哪种方式,都应从一个如下所示的pom.xml文件开始:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.okta.example</groupId> <artifactId>okta-shiro-jaxrs-example</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> </project>
接下来,添加依赖项:
<dependencies> <dependency> <groupId>com.okta.shiro</groupId> <artifactId>okta-shiro-plugin</artifactId> <version>0.1.0</version> </dependency> <dependency> <groupId>javax.ws.rs</groupId> <artifactId>javax.ws.rs-api</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-jaxrs</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-servlet-plugin</artifactId> <version>1.5.3</version> <scope>runtime</scope> </dependency> <!-- logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>1.7.30</version> <scope>runtime</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> <scope>runtime</scope> </dependency> <!-- JAX-RS, runtime only dependencies --> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-servlet</artifactId> <version>2.30.1</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.glassfish.jersey.core</groupId> <artifactId>jersey-server</artifactId> <version>2.30.1</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> <version>2.30.1</version> <scope>runtime</scope> </dependency> </dependencies>
为了使运行WAR文件变得容易,我们可以将Jetty Maven插件添加到pom文件中:
<build> <plugins> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.27.v20200227</version> <configuration> <httpConnector> <port>8000</port> </httpConnector> </configuration> </plugin> </plugins> </build>
创建一个JAX-RS端点 JAX-RS应用程序至少包含两部分:用于处理请求的REST资源/端点,以及将Application它们全部保持在一起的类。这些资源只是具有注释的Java对象,这些注释将HTTP请求映射到方法。
创建一个简单的资源,以在其中显示当前用户的电子邮件地址 src/main/java/com/okta/example/shiro/SecureEndpoint.java
src/main/java/com/okta/example/shiro/SecureEndpoint.java
package com.okta.example.shiro; import org.apache.shiro.authz.annotation.RequiresAuthentication; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.Context; import javax.ws.rs.core.SecurityContext; @Path("/") @Produces({"plain/text"}) public class SecureResource { @GET @RequiresAuthentication public String showUser(@Context SecurityContext securityContext) { return "Current User: " + securityContext.getUserPrincipal().getName(); } }
如果您需要从访问令牌中获取其他信息,请将用户主体转换为OktaJwtPrincipal并使用以下getClaim()方法:
OktaJwtPrincipal jwtPrincipal = (OktaJwtPrincipal) securityContext; jwtPrincipal.getClaim("your-claim-key");
创建一个JAX-RS应用程序 JAX-RSApplication类定义与应用程序关联的元数据和组件。大多数JAX-RS实现都提供帮助程序类,该类自动扫描您的资源,但是由于此示例可与任何实现一起使用,因此您将直接配置它们。
创建一个从延伸的类Application中src/main/java/com/okta/example/shiro/RestApplication.java:
package com.okta.example.shiro; import org.apache.shiro.web.jaxrs.ShiroFeature; import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/") public class RestApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); classes.add(ShiroFeature.class); classes.add(SecureResource.class); return classes; } }
配置Apache Shiro以使用OAuth 2.0 可以通过几种不同的方式配置Apache Shiro:以编程方式,通过Spring和Guice进行依赖注入,或使用“ ini”文件。为了使事情更加集中,我将使用shiro.ini位于中的一个简单文件src/main/resources:
[main] # Define the Okta realm oktaJwtRealm = com.okta.shiro.realm.OktaResourceServerRealm # Configure your issuer oktaJwtRealm.issuer = https://{yourOktaDomain}/oauth2/default [urls] # use the `authcBearer` filter to process Bearer tokens /** = authcBearer
如果您有需要匿名访问的资源,请使用-authcBearer[permissive]只需确保正确注释了所有端点!
-authcBearer[permissive]
添加一个 web.xml 您可能会问自己“真的是web.xml文件吗?” 从技术上讲,您不需要一个,而可以将Maven War Plugin配置为不需要web.xml。
Maven War Plugin
或者,只需将一个空添加web.xml到src/main/webapp:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee https://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> </web-app>
运行安全的REST应用程序 您可以使用构建项目./mvnw package。只需从target目录中获取war文件,将其复制到您喜欢的容器中,然后启动它。相反,我们将使用Jetty Maven插件。在项目目录中,运行:
./mvnw package
curl localhost:8000/ -v
此命令启动在port上运行的服务器8000。使用curl发出请求:
< HTTP/1.1 401 Unauthorized < Date: Thu, 09 Apr 2020 17:50:49 GMT < WWW-Authenticate: Bearer realm="application" < Content-Length: 0 < Server: Jetty(9.4.27.v20200227)
服务器401未提供访问令牌,因此返回了状态代码。有几种获取访问令牌的方法。哪种选择最适合您,取决于您在何处以及如何访问REST应用程序。通常,正在调用REST API的应用程序已经具有访问令牌。例如,SPA移动应用程序或另一个Web应用程序可能已经具有经过身份验证的用户。为了进行测试,我们将设置OIDC调试器。
创建一个OAuth 2.0应用程序 登录到您的Okta管理控制台。如果您刚创建一个新的Okta帐户但尚未登录,请单击收件箱中的激活链接。
在右上角记下组织URL;我将{yourOktaDomain}在下一节中提到它。
登录后,从顶部菜单中选择应用程序→添加应用程序。然后,选择Web →下一步。
为您的应用程序命名,例如:“ Shiro JAX-RS Example”。
将登录重定向URI设置为https://oidcdebugger.com/debug
https://oidcdebugger.com/debug
检查隐式(Hybrid)
点击完成
应用程序设置记下Client ID,下一步将需要它。
使用OIDC调试器获取令牌 转到https://oidcdebugger.com/,并使用以下值填充表单:
Authorize URI - -{yourOktaDomain}/oauth2/default/v1/authorize
ClientID -{yourClientID}从之前的步骤
State- this is a test(可以是任何值)
Response type-选择令牌
对所有其他字段使用默认值
按下发送请求按钮。
如果您使用隐身浏览器/专用浏览器,这可能会提示您再次登录。一旦成功页面加载,请复制访问令牌,并创建一个环境变量:
export TOKEN=" <your-access-token-here>"
现在有了令牌,您可以向您的JAX-RS服务器发出另一个请求:
curl localhost:8000/ -H "Authorization: Bearer $TOKEN" Current User: <your-email-address>
就像这样,您已经向您的JAX-RS应用程序发出了经过身份验证的请求!
了解有关安全应用程序的更多信息 在本教程中,我向您展示了如何使用Apache Shiro和Okta保护简单的JAX-RS应用程序。这种相同的资源服务器技术也可以与其他基于servlet的Web应用程序一起使用。
原文链接:http://codingdict.com/