在泽西岛获得rest服务
我对Web服务非常陌生。 我已经使用Jersey 2与Spring集成了一些REST服务。 现在我需要使用用户名/密码进行身份validation来保护这些rest服务。 我被告知不要使用Spring安全性。
我不知道该怎么做。 我在网上搜索,但各种链接显示各种实现,我无法决定如何继续它。
我知道这是一个模糊的问题但请在这方面提供帮助。
使用用户名和密码进行身份validation的常用方法是使用基本身份validation 。 基本上客户端需要发送请求标头Authorization
,标头值为Basic Base64Encoded(username:password)
。 所以我的用户名是peeskillet
,我的密码是pass
,作为客户端,我应该将标题设置为
Authorization: Basic cGVlc2tpbGxldDpwYXNz
在servlet环境中,容器应该支持基本身份validation。 您可以在web.xml上配置此支持。 您可以在48.2保护 Java EE的Web应用程序教程中看到一个示例。 您还会在一个示例中注意到
CONFIDENTIAL
这是为了SSL支持。 建议用于基本身份validation。
如果您不想处理使用安全域和登录模块,领域等的麻烦,那么需要自定义servlet支持,或者如果您不在servlet环境中,那么实现Basic Auth在ContainerRequestFilter
中真的不是太难。
您可以在jersey / examples / https-clientserver-grizzly上看到完整的示例。 您应该专注于SecurityFilter
filter中的基本流程就是这样的
-
获取
Authorization
标头。 如果它不存在,则抛出AuthenticationException
。 在这种情况下,AuthenticationExceptionMapper
将发送标题"WWW-Authenticate", "Basic realm=\"" + e.getRealm() + "\"
,这是Basic Auth协议的一部分 -
一旦我们有了标题,我们解析它只是为了获得Base64编码的用户名:密码。 然后我们解码它,然后拆分它,然后分开用户名和密码。 如果此进程中的任何一个失败,则再次抛出映射到400 Bad Request的
WebApplicationException
。 -
检查用户名和密码。 示例源代码只检查用户名是否为
user
,密码是否为password
,但您需要使用filter中的某些服务来validation此信息。 如果其中任何一个失败,则抛出AuthenticationException
-
如果一切顺利,则从
authenticate
方法创建User
,并将其注入Authorizer
(这是一个SecurityContext
)。 在JAX-RS中,SecurityContext
通常用于授权。
对于授权,如果要保护某些资源的某些区域,可以对类或方法使用@RolesAllowed
批注。 通过注册RolesAllowedDynamicFeature
,Jersey支持此注释。
引擎盖下发生的事情是SecurityContext
将从请求中获得。 通过我链接到的示例,您可以看到Authorizer
,它有一个重写方法isUserInRole
。 将调用此方法来检查@RolesAllowed({"ADMIN"})
。 因此,在创建SecurityContext
,应确保在重写方法中包含用户的角色。
要进行测试,您只需使用浏览器即可。 如果一切设置正确,当您尝试访问资源时,您应该看到(在Firefox中)一个对话框,如本文所示。 如果你使用cURL ,你可以这样做
C:/>curl -v -u username:password http://localhost:8080/blah/resource
这将发出基本身份validation请求。 由于-v
开关,您应该看到所有涉及的标头。 如果您只想使用客户端API进行测试,可以在此处查看如何进行设置。 在上述三种情况中的任何一种情况下,Base64编码都将为您完成,因此您不必担心它。
至于SSL,您应该查看容器的文档,以获取有关如何设置它的信息。
安全性主要有两种:
- 基于容器
- 基于应用
保护spring应用程序的标准方法是使用Spring Security(以前称为Acegi)。 知道为什么你不被允许使用它会很有趣。
你可以使用基于容器的安全性,但我猜你使用spring也排除了这个选项。 由于选择Spring通常是为了避免使用完整的J2EE容器(编辑:虽然如下所述,但是大多数普通的servlet容器都允许你实现各种基于容器的安全方法)
这实际上只留下一个选项,即推出自己的安全性。
您对Jersey的使用表明这可能是一个REST应用程序。 在这种情况下,您确实应该坚持使用标准的HTTP身份validation方法,这些方法具有以下相同强度的相反顺序:
- BASIC
- 消化
- 形成
- 证书
REST应用程序通常被认为是“无状态”,它基本上排除了基于表单的身份validation(因为您需要使用Session),而您将使用BASIC,Digest和Certificate。
你的下一个问题是,我是谁在validation。 如果您可以根据他们请求的URL知道用户的用户名和密码(例如,如果它是所有用户的一组凭据),那么Digest是最好的选择,因为密码永远不会被发送,只有哈希。 如果您无法知道密码(因为您要求第三方系统对其进行validation等),那么您将无法使用BASIC。 但是,您可以通过使用SSL来增强BASIC的安全性,或者更好地将BASIC与客户端证书身份validation相结合。 事实上,基于HTTPS的BASIC身份validation是保护大多数REST应用程序的标准技术。
您可以轻松实现查找身份validation标头的Servletfilter并自行validation凭据。 这种filter有很多例子,它是一个自包含的类文件。 如果没有找到凭证,则filter返回401,在响应头中传递基本身份validation的提示。 如果凭据无效,则返回403.应用程序安全性本身几乎是整个职业,但我希望这会有所帮助。
正如之前的post所说,你可以使用不同的选项,实现的开销也各不相同。 从实际的角度来看,如果您要从这开始并寻找一种简单实现的舒适方式,我建议使用BASIC身份validation的基于容器的选项。
如果使用tomcat,则可以设置一个实现起来相对简单的领域 。 您可以使用JDBCRealm,它从数据库中的指定列获取用户和密码,并通过server.xml和web.xml进行配置。 每次您尝试访问您的应用程序时,这都会自动提示您输入凭据。 您没有任何应用程序端实现。
我现在可以告诉你的是,你已经完成了将Jersey与Spring整合在一起的大部分“脏”工作。 我建议您使用基于应用程序的解决方案,它不会将您绑定到特定容器。 Spring Security一开始可能会令人生畏,但是当你驯服野兽时,你会发现它实际上是一只友善的小狗。
事实上,只需实现接口,Spring Security就可以进行大规模定制。 并且有很多文档和支持。 此外,您已经拥有一个基于Spring的应用程序。
因为你所寻求的只是指导,我可以为你提供一些教程。 您可以利用此博客。
http://www.baeldung.com/rest-with-spring-series/ http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security- 3-1-部分-3 /
其实昨天做了这件事。
所以这真的是你想要实现的东西。 我的理由是使用移动设备和One-Page-App JavaScript来运行这个东西。
基本上,您需要做的就是生成某种类型的标头,该标头在客户端将要进行的每个连续请求中都需要。
因此,您在等待具有用户/密码的post时执行端点:
@Path("/login") public class AuthenticationResource { @POST @Consumes("application/json") public Response authenticate(Credentials credential) { boolean canBeLoggedIn = (...check in your DB or anywher you need to) if (canBeLoggedIn) { UUID uuid = UUID.randomUUID(); Token token = new Token(); token.setToken(uuid.toString()); //save your token with associated with user (...) return Response.ok(token).type(MediaType.APPLICATION_JSON_TYPE).build(); } else { return Response.status(Response.Status.UNAUTHORIZED).build(); } }
}
现在您需要保护需要该令牌的资源:
@Path("/payment") @AuthorizedWithToken public class Payments { @GET @Produces("application/json") public Response sync() { (...) } }
注意@AuthorizedWithToken
注释。 您可以使用特殊元注释@NameBinding
自行创建此注释
@NameBinding @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface AuthorizedWithToken {}
现在,对于实现标头检查的filter:
@AuthorizedWithToken @Provider public class XAuthTokenFilter implements ContainerRequestFilter { private static String X_Auth_Token = "X-Auth-Token"; @Override public void filter(ContainerRequestContext crc) throws IOException { String headerValue = crc.getHeaderString(X_Auth_Token); if (headerValue == null) { crc.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Missing " + X_Auth_Token + " value").build()); return; } if(! TOKEN_FOUND_IN_DB) { crc.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Wrong " + X_Auth_Token + " value").build()); return; } } }
您可以创建任意数量的自己的注释,检查http请求中的各种内容并混合它们。 但是你需要注意优先级,但实际上很容易找到。 此方法需要使用https
但这很明显。
- 在JTextArea中的列中对齐字符串
- hadoop java.net.URISyntaxException:绝对URI中的相对路径:rsrc:hbase-common-0.98.1-hadoop2.jar
- Java EE WebApp + icefaces中的长时间运行任务
- Java int division令我困惑
- 通过ByteBuffer和CQL 3将Java对象序列化为Cassandra 1.2
- Long vs BigInteger
- JOGL没有自动释放池
- Java:使用apache POI如何将ms word文件转换为pdf?
- Spring 4 + Hibernate 5 = org.springframework.orm.jpa.EntityManagerHolder无法强制转换为org.springframework.orm.hibernate5.SessionHolder
- Java如何对链表进行排序?
- 列表与列表