2017-01-17 5 views
1

Я пытаюсь создать защищенный Restlet ресурс на основе этого примера http://bipinkunjumon.blogspot.com/2013/05/restlet-application-for-accessing.html:Как создать защищенный ресурс Restlet?

public class PartApp extends Application { 
public static final String ROOT_URI="localhost:8151/accounts/{accountId}"; 
public static void main(String[] args) throws Exception 
{ 
    // Create a component 
    Component component = new Component(); 
    component.getServers().add(Protocol.HTTP, 8151); 
    component.getClients().add(Protocol.FILE); 

    // Create an application 
    Application application = new PartApp(); 

    // Attach the application to the component and start it 
    component.getDefaultHost().attachDefault(application); 
    component.start(); 
} 

@Override 
public Restlet createInboundRoot() 
{ 
    // Create a simple password verifier 
    MapVerifier verifier = new MapVerifier(); 
    verifier.getLocalSecrets().put("scott", "tiger".toCharArray()); 



    // Create a Guard 
    ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
      getContext(), ChallengeScheme.HTTP_BASIC, "Tutorial"); 
    authenticator.setVerifier(verifier); 

    // Create a Directory able to return a deep hierarchy of files 
    Directory directory = new Directory(getContext(), ROOT_URI); 

    directory.setListingAllowed(true); 
    authenticator.setNext(directory); 
    return authenticator; 
} 
} 

Но это работает для всех серверных ресурсов. Например, я не могу ввести localhost: 8111 без логина и пароля. Но мне нужно защитить только один ресурс: localhost: 8151/accounts/{accountId} и предоставить бесплатный доступ для других. Как я могу это сделать?

+0

Вы используете tomcat для развертывания приложения-рестарта? Или это отдельное приложение? если вы используете tomcat, то эта ссылка может помочь: http://stackoverflow.com/questions/10691490/how-do-i-configure-the-web-xml-for-multiple-restlet-applications –

+0

Нет, я не используя tomcat, и, несмотря на ссылочный пример, все мои ресурсы принадлежат одному и тому же приложению. – vitaliy4us

ответ

2

на основе кода, который я нашел здесь: https://stackoverflow.com/a/2220624/444028, я сделал этот крошечный проект с использованием Java 7 и Restlet SE 2.3.9:

Есть 6 файлов Java (Все это на стороне сервера коды) в 2-х пакетах в этом проекте:

  1. пакета
    com.blogspot.javarestlet.httpbasicauth.server.app
    1. AdminAppStart.java (расширение применения для авторизованного кли ЛОР)
    2. ClientAppStart.java (расширение приложений для неавторизованного клиента) [Примечание: Это не код на стороне клиента.]
    3. Main.java (Тот, который запускает сервер)
  2. упаковываются
    com.blogspot.javarestlet.httpbasicauth.server.resources
    1. HelloWorldAdminServerResource.java (Чтобы быть присоединен с AdminAppStart)
    2. HelloWorldClientServerResource.java (T о быть приложен ClientAppStart)
    3. HelloWorldDefaultServerResource.java (Несколько ненужный файл класса)

Вот код каждого файла:

AdminAppStart.java

package com.blogspot.javarestlet.httpbasicauth.server.app; 

import org.restlet.Application; 
import org.restlet.Context; 
import org.restlet.Restlet; 
import org.restlet.data.ChallengeScheme; 
import org.restlet.routing.Router; 
import org.restlet.security.ChallengeAuthenticator; 
import org.restlet.security.MapVerifier; 

import com.blogspot.javarestlet.httpbasicauth.server.resources.HelloWorldAdminServerResource; 
import com.blogspot.javarestlet.httpbasicauth.server.resources.HelloWorldDefaultServerResource; 

public class AdminAppStart extends Application { 
    private ChallengeAuthenticator authenticator; 

    private ChallengeAuthenticator createAuthenticator() { 
     Context context = getContext(); 
     final boolean optional = false; 
     ChallengeScheme challengeScheme = ChallengeScheme.HTTP_BASIC; 
     String realm = "Example site"; 

     MapVerifier verifier = new MapVerifier(); 
     verifier.getLocalSecrets().put("scott", "tiger".toCharArray()); 

     ChallengeAuthenticator auth = new ChallengeAuthenticator(context, optional, challengeScheme, realm, verifier); 
     return auth; 
    } 

    @Override 
    public Restlet createInboundRoot() { 
     this.authenticator = createAuthenticator(); 

     Router router = new Router(); 
     router.attach("/user", HelloWorldAdminServerResource.class); 
     router.attach("", HelloWorldDefaultServerResource.class); 

     authenticator.setNext(router); 
     return authenticator; 
    } 

} 

ClientAppStart.java

package com.blogspot.javarestlet.httpbasicauth.server.app; 

import org.restlet.Application; 
import org.restlet.Restlet; 
import org.restlet.routing.Router; 

import com.blogspot.javarestlet.httpbasicauth.server.resources.HelloWorldClientServerResource; 

public class ClientAppStart extends Application { 
@Override 
public Restlet createInboundRoot() { 
    Router router = new Router(); 
    router.attach("/clientres/hello", HelloWorldClientServerResource.class); 
    return router; 
} 
} 

Main.java

package com.blogspot.javarestlet.httpbasicauth.server.app; 

import org.restlet.Application; 
import org.restlet.Component; 
import org.restlet.data.Protocol; 

public class Main { 
    public static void main(String[] args) throws Exception 
    { 
     // Create a component 
     Component component = new Component(); 
     component.getServers().add(Protocol.HTTP, 8151); 
     component.getClients().add(Protocol.HTTP); 

     // Create an application 
     Application application = new ClientAppStart(); 

     // Attach the application to the component and start it 
     component.getDefaultHost().attach("/userx",application); 
     component.getDefaultHost().attach("/admin/accounts/abc123",new AdminAppStart()); 
     component.start(); 
    } 
} 

HelloWorldAdminServerResource.java

package com.blogspot.javarestlet.httpbasicauth.server.resources; 

import org.restlet.resource.Get; 
import org.restlet.resource.ServerResource; 

public class HelloWorldAdminServerResource extends ServerResource { 
    @Get 
    public String $get() 
    { 
     return "Hello Admin"; 
    } 
} 

HelloWorldClientServerResource.java

package com.blogspot.javarestlet.httpbasicauth.server.resources; 

import org.restlet.resource.Get; 
import org.restlet.resource.ServerResource; 

public class HelloWorldClientServerResource extends ServerResource { 
@Get 
public String $get() 
{ 
    return "Hello Client"; 
} 
} 

HelloWorldDefaultServerResource.Java

package com.blogspot.javarestlet.httpbasicauth.server.resources; 

import org.restlet.resource.Get; 
import org.restlet.resource.ServerResource; 

public class HelloWorldDefaultServerResource extends ServerResource{ 
@Get 
public String $get() 
{ 
    return "please enter a sub-url after abc123"; 
} 
} 

Вот локоны журнал запрос-ответ:

C:\Users\abhishek>curl -i "http://localhost:8151/userx/clientres/hello" 
HTTP/1.1 200 OK 
Content-type: text/plain; charset=UTF-8 
Content-length: 12 
Server: Restlet-Framework/2.3.9 
Accept-ranges: bytes 
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept 
Date: Mon, 23 Jan 2017 11:37:01 GMT 

Hello Client 

====================================================================== 

C:\Users\abhishek>curl -i -H "Authorization: Basic c2NvdHQ6dGlnZXI=" "http://localhost:8151/admin/accounts/abc123" 
HTTP/1.1 200 OK 
Content-type: text/plain; charset=UTF-8 
Content-length: 35 
Server: Restlet-Framework/2.3.9 
Accept-ranges: bytes 
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept 
Date: Mon, 23 Jan 2017 11:35:07 GMT 

please enter a sub-url after abc123 

====================================================================== 

C:\Users\abhishek>curl -i -H "Authorization: Basic c2NvdHQ6dGlnZXI=" "http://localhost:8151/admin/accounts/abc123/user" 
HTTP/1.1 200 OK 
Content-type: text/plain; charset=UTF-8 
Content-length: 11 
Server: Restlet-Framework/2.3.9 
Accept-ranges: bytes 
Vary: Accept-Charset, Accept-Encoding, Accept-Language, Accept 
Date: Mon, 23 Jan 2017 11:35:04 GMT 

Hello Admin 

====================================================================== 

C:\Users\abhishek>curl -i "http://localhost:8151/admin/accounts/abc123/user" 
HTTP/1.1 401 Unauthorized 
Content-type: text/html; charset=UTF-8 
Content-length: 424 
Www-authenticate: Basic realm="Example site" 
Server: Restlet-Framework/2.3.9 
Accept-ranges: bytes 
Date: Mon, 23 Jan 2017 12:48:08 GMT 

<html> 
<head> 
    <title>Status page</title> 
</head> 
<body style="font-family: sans-serif;"> 
<p style="font-size: 1.2em;font-weight: bold;margin: 1em 0px;">Unauthorized</p> 
<p>The request requires user authentication</p> 
<p>You can get technical details <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2">here</a>.<br> 
Please continue your visit at our <a href="/">home page</a>. 
</p> 
</body> 
</html> 

Попробуйте это и скажите нам, если вы столкнулись с какими-либо проблемами.

Добавлено О 2017-01-24 1524:

Поскольку Аскер спросил «.. ли это общее правило, делать такие вещи, как это путем создания отдельных приложений ..?»

Вот ответ на этот вопрос в простейшем Вкратце:

Application.createInboundRoot() должен возвращать Restlet и вот подклассы класса Restlet, полученные здесь: https://restlet.com/technical-resources/restlet-framework/javadocs/2.3/jee/api/

 
org.restlet.Restlet 
^ 
| 
|--org.restlet.Application 
| 
|--org.restlet.Component 
| 
|--org.restlet.Connector 
|^
| |--org.restlet.Client 
| | 
| |--org.restlet.Server 
| 
|--org.restlet.routing.Filter 
|^
| | 
| |--org.restlet.security.Authenticator 
| |^
| | | 
| | |--org.restlet.security.CertificateAuthenticator 
| | | 
| | |--org.restlet.security.ChallengeAuthenticator 
| | 
| |--org.restlet.security.Authorizer 
| |^
| | | 
| | |--org.restlet.security.ConfidentialAuthorizer 
| | | 
| | |--org.restlet.security.MethodAuthorizer 
| | | 
| | |--org.restlet.security.RoleAuthorizer 
| | 
| |--org.restlet.routing.Extractor 
| | 
| |--org.restlet.routing.Route 
| |^
| | | 
| | |--org.restlet.routing.TemplateRoute 
| | 
| |--org.restlet.routing.Validator 
| 
|--org.restlet.resource.Finder 
|^
| | 
| |--org.restlet.resource.Directory 
| 
|--org.restlet.routing.Redirector 
| 
|--org.restlet.routing.Router 
| 
|--org.restlet.util.WrapperRestlet 

Если вы идете через документацию и образцы каждого класса (каждый из них сделает этот ответ слишком длинным), вы обнаружите, что есть другие способы сделать это, но создание отдельных Application для каждого из них является самым простым из всех способов.

+1

Большое спасибо. Меня устраивает. Является ли это общим правилом делать такие вещи, создавая отдельные приложения для ресурсов (например, AdminAppStart и ClientAppStart в примере)? – vitaliy4us

+0

И еще один вопрос, касающийся авторизации. Я создал приложение на основе вашего примера. Я защитил маршрут localhost: 8151/accounts/{accountId} и список пользователей с учетными данными: «user1», «user1»; «user2», «user2»; .... Идентификаторы пользователей: 1, 2 .... Таким образом, для каждой учетной записи пользователя может быть установлен localhost: 8151/accounts/1; .... Например, я перехожу к localhost: 8151/accounts/1 и вводим учетные данные для первого пользователя. С тех пор любые другие учетные записи (например, localhost: 8151/accounts/2) становятся доступными без каких-либо учетных данных. Как их защитить? – vitaliy4us

+0

@ vitaliy4us то, что вам понадобится здесь, является RoleAuthorizer. см. эти 2 ссылки: 1. [Модифицированное разрешение] (https://restlet.com/technical-resources/restlet-framework/guide/2.3/core/security/authorization), 2. [java - Создание автоответчика Restlet для мелкозернистой авторизации] (http://stackoverflow.com/questions/16499192/creating-a-restlet-authorizer-for-fine-grained-authorization). В первой ссылке вы найдете комбинацию аутентификации + авторизация –

Смежные вопросы