针对不同请求方法的Java httpServer基本身份验证
我在Java中使用一个非常简单的httpServer作为api rest,其中包含GET、POST、PUT和DELETE。我使用的是基本身份验证,我有两个类Authentication.java和authorization.java,用于验证和检查用户的权限 所以,我希望所有用户(经过身份验证的)都能够从我的api rest中获取信息,但只有具有特定权限的用户才能发布、放置和删除。那我该怎么做呢 这就是我得到的针对不同请求方法的Java httpServer基本身份验证,java,rest,basic-authentication,httpserver,Java,Rest,Basic Authentication,Httpserver,我在Java中使用一个非常简单的httpServer作为api rest,其中包含GET、POST、PUT和DELETE。我使用的是基本身份验证,我有两个类Authentication.java和authorization.java,用于验证和检查用户的权限 所以,我希望所有用户(经过身份验证的)都能够从我的api rest中获取信息,但只有具有特定权限的用户才能发布、放置和删除。那我该怎么做呢 这就是我得到的 public class Server { private static Ht
public class Server {
private static HttpServer server;
public static void start() throws IOException {
server = HttpServer.create(new InetSocketAddress(8000), 0);
HttpContext ctx = server.createContext("/users", new UserHandler());
ctx.setAuthenticator(new ApiRestBasicAuthentication("users"));
server.start();
}
}
这是我最基本的证明
public class ApiRestBasicAuthentication extends BasicAuthenticator {
private UserAuthentication authentication = new UserAuthentication();
public ApiRestBasicAuthentication(String realm) {
super(realm);
}
@Override
public boolean checkCredentials(String user, String pwd) {
int authCode = authentication.authenticate(user, pwd);
return authCode == UserAuthentication.USER_AUTHENTICATED;
}
}
现在,检查凭据只是检查用户是否经过身份验证。
但是我想检查,如果方法是POST、DELETE或PUT,我还应该检查具体的凭据。但是我怎样才能在我的ApiRestBasicAuthentication中获得该方法呢?我在我的处理程序类中这样做
public void handle(HttpExchange httpExchange) throws IOException {
String method = httpExchange.getRequestMethod();
if ("post".equalsIgnoreCase(method)) {
createUser(httpExchange);
} else if ("get".equalsIgnoreCase(method)) {
readUsers(httpExchange);
} else if ("put".equalsIgnoreCase(method)) {
updateUser(httpExchange);
} else if ("delete".equalsIgnoreCase(method)) {
deleteUser(httpExchange);
}
}
也许这应该用另一种方式。
有什么想法吗
非常感谢。解决这个问题的方法可能很多。以下是我的建议之一:
由于还没有提供其他实现,我无法给出更详细的答案,也无法确定这是否适用于您 一个简单的方法是改变你的 ApiRestBasicAuthentication,如:
public class ApiRestBasicAuthentication extends BasicAuthenticator {
private UserAuthentication authentication = new UserAuthentication();
public ApiRestBasicAuthentication(String realm) {
super(realm);
}
@Override
public Authenticator.Result authenticate(HttpExchange exch) {
Authenticator.Result result=super.authenticate(exch);
if(result instanceof Authenticator.Success) {
HttpPrincipal principal=((Authenticator.Success)result).getPrincipal();
String requestMethod=exch.getRequestMethod();
if( ADD SOME LOGIC HERE FOR PRINCIPAL AND REQUEST METHOD) {
return new return new Authenticator.Failure(401);
}
return result;
}
}
@Override
public boolean checkCredentials(String user, String pwd) {
int authCode = authentication.authenticate(user, pwd);
return authCode == UserAuthentication.USER_AUTHENTICATED;
}
}
并为您希望验证失败的请求/用户添加一些逻辑。我在这里向您展示了如何在authenticate方法中获取该方法,但是您需要指定凭据的类型
另一个解决方案是,如果您检查BasicAuthenticator的源代码,您可以看到它是如何实现
authenticate
方法的,您可以以类似的方式创建自己的实现,而不是扩展BasicAuthenticator,并使用get方法,而不仅仅是用户名和密码。您可以看到源代码,我相信您将能够找到自己的方法;)
通常在企业应用程序中,您可以使用一些外部安全管理系统——例如,如果您使用Spring(当前java web应用程序中的事实标准)您可以使用spring安全性,并以更具声明性的方式执行此类安全模式和过滤器我认为您应该创建一个
AuthenticationInterceptor
和旁路获取那里的请求,并相应地为rest非获取
请求应用身份验证机制
public class AuthenticationInterceptor extends HandlerInterceptorAdapter {
@Autowired
private ApiRestBasicAuthentication apiRestBasicAuthentication;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
switch (request.getMethod()) {
case "GET" :
// by-passing all GET requests
return true;
default :
return apiRestBasicAuthentication.checkCredentials(username, password);
}
}
}
虽然上面的答案可能对您有效,但我认为您也应该考虑使用定义在Web.xml中的角色和安全约束,并使用ReleSead注释在REST资源中使用。然后,这允许您单独或在REST资源/类级别专门允许方法的权限
在web.xml中,这类似于:-
<security-role>
<role-name>SERVERTOSERVER</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>REST API description</web-resource-name>
<url-pattern>/<path name>/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<description>Only allow users
from following roles</description>
<role-name>SERVERTOSERVER</role-name>
</auth-constraint>
</security-constraint>
服务器到服务器
RESTAPI描述
//*
得到
,
如果有帮助,这里有另一种针对基于Jersey的应用程序的解决方案:我想您需要一些授权方面(或过滤器或拦截器提供的类似功能),只有在用户获得授权的情况下才会响应非GET,尽管我现在无法帮您提供完整答案。找出哪些(方面、过滤器、拦截器)是可用的,并阅读相关内容。这可能会起作用,因为我可以检查过滤器中的方法(POST、GET、PUT等),但如何在过滤器中获取请求中发送的用户名?我的ApiRestBasicAuthentication有一个checkCredentials()函数,它接收用户和密码,但在过滤器中我只有httpExchange对象,并且用户名/密码是加密的。我建议您使用spring security
。看看下面的答案:您指的是什么web.xml
?@RolesAllowed
注释从何而来?在没有交叉检查的情况下,我假设您正在讨论一个特定于Tomcat服务器的解决方案。因此,这个答案不符合上面的问题。javax.annotation.security.RolesAllowed,我已经给出了一些基于角色访问(基于tomcat/jersey的RESTAPI)的示例,正如您自己所说,您的解决方案是基于tomcat/jersey的。因此,它不能与com.sun.net.HttpServer
-包中的HttpServer
(或HttpsServer
)一起使用。@RolesAllowed是一个与安全角色一起使用的java注释。我怀疑你说的完全正确。
<security-role>
<role-name>SERVERTOSERVER</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>REST API description</web-resource-name>
<url-pattern>/<path name>/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<description>Only allow users
from following roles</description>
<role-name>SERVERTOSERVER</role-name>
</auth-constraint>
</security-constraint>