一般来说,我对Restlet和REST都很陌生,我希望为运行中的服务器/数据库实现一个Restlet。到目前为止,路由和寻址似乎运行良好,但我需要一些关于如何处理身份验证和授权的提示。
情况:有一些资源,只有某些用户才能以某种方式进行交互。例如,User1可能可以获得资源,但不能放置任何东西,而User2可以两者都做,User3甚至可能不会读取,而User4是唯一允许使用DELETE的。
当然,MethodAuthorizer听起来很有希望,但它似乎只区分匿名用户和(所有)身份验证用户。另一个爪上的RoleAuthorizer不区分GET、PUT或其他请求方法,只区分资源。
我怎样才能授权某些用户只执行特定的任务呢?有没有办法组合授权器,或者让他们执行多个测试?我是否必须编写一个自定义授权程序(我将如何编写)?
另外,是否可以使用其他地方提供给身份验证者的凭据,例如将它们作为String传播到另一个方法?(如何)如何获得当前请求的标识符和秘密?
发布于 2015-05-04 11:53:01
事实上,我认为您应该利用Restlet的角色支持。事实上,Restlet提供了两个关于安全的附加元素:
Verifier,它根据请求中提供的凭据对用户进行身份验证。Enroler,它加载身份验证用户的角色。下面是一个基本身份验证的示例:
@Override
public Restlet createInboundRoot() {
Router router = (...)
Verifier verify = new MyVerifier(...);
Enroler enroler = new MyEnroler(...);
ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
ChallengeScheme.HTTP_BASIC, "connector");
guard.setVerifier(verifier);
guard.serEnrole(enroler);
guard.setNext(router);
return guard;
}Verifier的实现如下所示:
public class MyVerifier extends SecretVerifier {
public int verify(String identifier, char[] secret)
throws IllegalArgumentException {
ApplicationUser user = loadUser(identifier);
//user contains both user hints and roles
if (user!=null
&& compare(user.getPassword().toCharArray(), secret)) {
Request request = Request.getCurrent();
request.getClientInfo().setUser(user);
return SecretVerifier.RESULT_VALID;
} else {
return SecretVerifier.RESULT_INVALID;
}
}
}Enroler的实现如下所示:
public class MyEnroler implements Enroler {
public void enrole(ClientInfo clientInfo) {
Request request = Request.getCurrent();
User user = request.getClientInfo().getUser();
if (user!=null) {
List<UserRole> roles = user.getRoles();
if (roles!=null) {
for (UserRole userRole : roles) {
// example of role creation
Role role = new Role(userRole.getName(), "");
clientInfo.getRoles().add(role);
}
}
}
}
}然后,在资源中,您可以检查Restlet请求中可用的角色,以确定是否允许通过身份验证的用户执行该方法:
public MyServerResource extends ServerResource {
private boolean hasRole(String expectedRole) {
List<Role> roles = request.getClientInfo().getRoles();
for (Role role : roles) {
if (role.getName().equals(expectedRole)) {
return true;
}
}
return false;
}
private void checkRole(String role) {
if (!hasRole(role)) {
throw new ResourceException(
Status.CLIENT_ERROR_FORBIDDEN);
}
}
@Get
public Representation getElement() {
checkRole("read");
}
@Put
public void updateElement(Representation repr) {
checkRole("update");
}
@Delete
public void deleteElement() {
checkRole("delete");
}
}这种方法有点入侵性。您还可以根据所使用的HTTP方法和角色进行更一般的操作。为此,我们需要实现一个自定义Authorizer并按如下方式注册:
Router router = (...)
Authorizer authorizer = new MyAuthorizer();
authorizer.setNext(router);
Verifier verify = new MyVerifier(...);
Enroler enroler = new MyEnroler(...);
ChallengeAuthenticator guard = new ChallengeAuthenticator(getContext(),
ChallengeScheme.HTTP_BASIC, "connector");
guard.setVerifier(verifier);
guard.serEnrole(enroler);
guard.setNext(authorizer);
return guard;
}这个Authorizer的实现可以是这样的:
public class MyAuthorizer extends Authorizer {
private String[] getRoles = new String[] { "read"};
private String[] putRoles = new String[] { "update"};
private String[] deleteRoles = new String[] { "delete"};
private boolean hasRoles(String[] expectedRoles) {
List<Role> roles = request.getClientInfo().getRoles();
for (String expectedRole : expectedRoles) {
for (Role role : roles) {
if (role.getName().equals(expectedRole)) {
return true;
}
}
}
return false;
}
private void checkRoles(String[] roles) {
if (!hasRole(roles)) {
throw new ResourceException(
Status.CLIENT_ERROR_FORBIDDEN);
}
}
public boolean authorize(Request request, Response response) {
if (!request.getClientInfo().isAuthenticated()) {
throw new ResourceException(
Status.CLIENT_ERROR_FORBIDDEN);
}
if ("GET".equals(request.getMethod().getName())) {
checkRoles(getRoles);
} else if ("PUT".equals(request.getMethod().getName())) {
checkRoles(putRoles);
} else if ("DELETE".equals(request.getMethod().getName())) {
checkRoles(deleteRoles);
}
return false;
}
}希望它能帮到你,蒂埃里
https://stackoverflow.com/questions/30028907
复制相似问题