2009-05-26 11 views
41

ジャージーではプログラム的にセッション管理やセキュリティを得る方法はありますか? Webアプリケーションセッション管理?または、トランザクション、セッション、およびセキュリティはすべて、Jerseyアプリケーションがデプロイされているコンテナによって処理されますか?ジャージーのセキュリティとセッション管理

+0

これについても調査を開始しました。私は何かを見つけたら返事を返します。 –

答えて

68

セッション管理は、Jerseyがデプロイされているコンテナの範囲です。ほとんどの場合、セッション管理を実行するコンテナ内にデプロイされます。

以下のコードは、セッションオブジェクトを取得してセッションに値を格納し、後続の呼び出しで値を取得するジャージリソースの簡単な例です。

@Path("/helloworld") 
public class HelloWorld { 

    @GET 
    @Produces("text/plain") 
    public String hello(@Context HttpServletRequest req) { 

     HttpSession session= req.getSession(true); 
     Object foo = session.getAttribute("foo"); 
     if (foo!=null) { 
      System.out.println(foo.toString()); 
     } else { 
      foo = "bar"; 
      session.setAttribute("foo", "bar"); 
     } 
     return foo.toString(); 


    } 
} 
+0

JAX-RS Webサービスのアクセスコントロールのいくつかの実装をしなければならないので、私はこれを必要としました。それについての助けも高く評価されます。 ありがとうございます、 Adhir – Adhir

+0

@Jack Cox:私はここで関連する質問を投稿しました:http://stackoverflow.com/questions/9676588/how-can-you-authenticate-using-the-jersey-client-against-a-jaas- enabled-web-serv 多分あなたはクライアント側(jersey-client)でこれを行う方法も知っているでしょうか? – carlspring

+0

@Jack Cox、1000ユーザーが同時にログインしたアプリケーションがあり、それぞれが 'session.setAttribute(" username "、username)'を設定しているとします。 Javaは、それぞれが異なる名前を持つ 'username'という名前の変数を持つ1000の異なるセッションがあることをJavaは理解していますか? – kasavbere

6

セッションに関するジャックの応答は正しいです。サーブレット仕様では、少なくともJavaEEコンテナ間の移植性はありますが、実行するコンテナに固有のものです。

セキュリティに関しては、少なくともJaaS(Java Authentication and Authorization Service)とservlet filterを使用して、JAX-RS固有のコードから分離する機会があります。このフィルタを使用してHTTP認証を実施し、認証に成功するとJaaS Subjectを適切なプリンシパルで設定できます。 JAX-RSリソースは、Subject上の適切なプリンシパルをチェックできます。スタック全体を制御するので、リソースで認証されたユーザーに頼ることができますが、これをテストしてください。リソースコードの現在の操作に基づいて認可を行うことができます。

+1

+1良いアイデアのように聞こえます。 Grizzlyでどのくらい正確に動作させることができましたか?私は新しい質問を開きました。 http://stackoverflow.com/questions/1682061/using-jaas-with-jersey-on-grizzly – User1

3

ジャージーセキュリティについては、ジャージーOAuthサポートをご覧ください。 OAuthは、システムのAPIを外部ユーザーに公開すると完全に適合します。 LinkedInのAPI

http://wikis.oracle.com/display/Jersey/OAuth

+0

リンクを修正してください – bekce

23

のようなたとえば、私はセッションが何かであることを、我々はは決して RESTfulなアプリケーションで使用...

Yegorは右されてはならないと思いました。我々はサーバ側の状態を決して維持してはならない。aaa従来のウェブアプリケーション。分離されたSOA指向のアプリケーションを構築する場合は、REST WebサービスにAPI /フレームワークを使用する必要はありません。サーバー側でグローバルなクライアント/サーバーの状態を維持する必要がある場合や、SOA指向の[web]アプリケーションとして記述できるものを暗黙的に構築していますが、Jerseyを[Web]開発フレームワークのように使用しています。誤って、あなたはWebサービスの性質を歪めています(RESTなど)。あなたそれは最初の答えで示唆された方法で行いますが、であってはいけません。最終的な結果は、Webサービスではなく、Webサービスのツールで構築された通常のアプリケーションだけです。

-_o

+2

これは必ずしも真実ではありません。セッションが応答をキャッシュする手段として使用されている場合は、パフォーマンスを向上させるためにセッションが使用されていると主張できます。キャッシング機構としてのセッションだけで、ステートレスなアプリケーションを作成することはできます。 – Vladimir

+0

ウェブサイトのようなウェブサイトは、ウェブアプリケーションを実行するためにウェブサービスの上にセッションを使用します。本質的に間違っているわけではありません。また、毎回資格情報を渡すことを望まないWebサービスを使用するようにユーザーを認証させることもできます。 – DiamondDrake

4

私は、クライアントがAuthorizationヘッダーを追加し、このようなRESTのMethodeの中でそれをテストすることによって、この問題を解決:

@GET 
@PRODUCES(MediaType.APPLICATION_JSON) 
public String returnClients(@Context HTTPServletRequest request(
    String auth = request.getHeader("Authorization"); 
    Account acc = null; 
    if (auth!=null) { 
     Account acc = Utils.LoginAccount(auth); 
    } 
    if (acc == null) 
    // not logged in, handle it gracefully 

をこのように認証セッションを開始せずにそこにあります。

+1

NB:HTTPS接続を強制しない限り、これは完全に安全ではありません。この場合、dropwizard-authも使用できます。 – Lambart

15

はい、可能です。ジャージーdocumentationは言う:リクエストの

セキュリティ情報を@Contextアノテーションを使用しJAX-RSに たSecurityContextインスタンスを注入することで利用可能です。注入された セキュリティコンテキストインスタンスは、HttpServletRequest APIで利用可能な機能 と同等の機能を提供します。注入されたセキュリティコンテキスト は、実際のJerseyアプリケーションの展開によって異なります。たとえば、サーブレットコンテナに Jerseyアプリケーションがデプロイされている場合、Jersey SecurityContextはサーブレット要求から取得したセキュリティコンテキスト の情報をカプセル化します。 Jerseyアプリケーション がGrizzlyサーバーにデプロイされている場合、SecurityContextは、Grizzlyリクエストから取得した 情報を返します。

例:

@Path("basket") 
public ShoppingBasketResource get(@Context SecurityContext sc) { 
    if (sc.isUserInRole("PreferredCustomer") { 
     return new PreferredCustomerShoppingBasketResource(); 
    } else { 
     return new ShoppingBasketResource(); 
    } 
} 

または

@Path("resource") 
@Singleton 
public static class MyResource { 
    // Jersey will inject proxy of Security Context 
    @Context 
    SecurityContext securityContext; 

    @GET 
    public String getUserPrincipal() { 
     return securityContext.getUserPrincipal().getName(); 
    } 
} 

それとも、注釈を箱から出してセキュリティをしたい場合は、these docsをご確認ください。

ジャージーはまた、あなたがたSecurityContextをカスタマイズすることができます:

SecurityContextが直接のgetSecurityContext()メソッドを介して ContainerRequestContextから取得することができます。 また、setContentContext(SecurityContext)メソッドを使用して、カスタム のリクエストコンテキストでデフォルトのSecurityContextを置き換えることもできます。 ContainerRequestFilterに カスタムSecurityContextインスタンスを設定すると、この セキュリティコンテキストインスタンスがJAX-RS リソースクラスフィールドに注入されます。この方法で、カスタムの 認証フィルタを実装して、独自のSecurityContextを に設定することができます。カスタム認証 要求フィルタの早期実行を確実に行うには、 の優先度を使用して、フィルタ優先度をAUTHENTICATIONに設定します。認証を早期に実行すると、 フィルタは、他のすべてのフィルタ、リソース、リソースメソッド とサブリソースロケータがカスタム SecurityContextインスタンスで確実に実行されます。

examples on how to use request filters with Jerseyを参照してください。次の例を確認してください:

import javax.annotation.Priority; 
import javax.ws.rs.Priorities; 

@Provider 
@Priority(Priorities.AUTHENTICATION) 
public class AuthRequestFilter implements ContainerRequestFilter { 
    @Context 
    HttpServletRequest webRequest; 

    @Override 
    public void filter(ContainerRequestContext requestContext) throws IOException { 
     final HttpSession session = webRequest.getSession(); 

     requestContext.setSecurityContext(new SecurityContext() { 
      @Override 
      public Principal getUserPrincipal() { 
       return new PrincipalImpl((String)session.getAttribute("USER_NAME")); 
      } 

      @Override 
      public boolean isUserInRole(String s) { 
       return false; 
      } 

      @Override 
      public boolean isSecure() { 
       return false; 
      } 

      @Override 
      public String getAuthenticationScheme() { 
       return null; 
      } 
     }); 
    } 
} 

警告! This was introduced in Jersey 2.4。 Glassfish 4.0.0は古いJersey 2.0を使用しているため、upgrade Jersey using these tipsにする必要があります(うまく動作することは証明されていません)。または、より良い方法はthe nightly build of Glassfish 4.0.1をダウンロードすることです。現時点では完全に安定していません。新しいバージョンがすぐにリリースされることを願っています。

更新日: 現時点(2014-02-14)Glassfish 4.0.1夜間ビルドはJersey 2.5.1を使用しており、コンテキスト注入は素晴らしい動作をします。

+1

すばらしい答え!ありがとう –

2

@pathを使用して、単一の名前空間でサービスをグループ化することができます。 例。

@Path("/helloworld") 
public class HelloWorld { 

    @GET 
    @Produces("text/plain") 
    public String hello() { 


     return ""; 


    } 
}
Instead of @Path("/helloworld") use 
@Path("admin/helloworld") to expose you class as rest and bind filter on "admin/" 
in web.xml as below. 

<servlet> 
      <servlet-name>jersey-serlvet</servlet-name> 
      <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
      <init-param> 
       <param-name>com.sun.jersey.config.property.packages</param-name> 
       <param-value>/</param-value> 
      </init-param> 
      <load-on-startup>1</load-on-startup> 
     </servlet> 
     <servlet-mapping> 
      <servlet-name>jersey-serlvet</servlet-name> 
      <url-pattern>/rest/*</url-pattern> 
     </servlet-mapping> 
     <filter> 
      <filter-name>myfilter</filter-name> 
      <filter-class>com.Filterclass</filter-class> 
     </filter> 
     <filter-mapping> 
      <filter-name>myfilter</filter-name> 
      <url-pattern>/rest/admin/*</url-pattern> 
     </filter-mapping> 

    public class Filterclass implements Filter { 
     public void doFilter(ServletRequest request, ServletResponse response, 
       FilterChain chain) 
       throws IOException, ServletException { 
        try{ 
         chain.doFilter(request, response); 
        }catch(Exception e){ 
        e.printStackTrace(); 
         } 
      } 
    }

あなたは、このフィルタクラスであなたのセッションを検証することができます。