

minSdkVersion : 19  
targetSdkVersion: 19

<http://komamitsu.hatenablog.com/entry/20120223/1330013934>  
上記を参考にAndroid上でNanoHTTPDを動かしています。

アクセス元の制限(IP制限)により配信可否を行いたいと思っています。

[AndroidWebServerActivity.java](https://gist.github.com/komamitsu/1893396#file-
androidwebserveractivity-java)の

[code]

    @Override
    public Response serve(String uri, String method,
            Properties header, Properties parms, Properties files) {
    
        final StringBuilder buf = new StringBuilder();
        for (Entry<Object, Object> kv : header.entrySet())
            buf.append(kv.getKey() + " : " + kv.getValue() + "\n");
    
        handler.post(new Runnable() {
            @Override
            public void run() {
                hello.setText(buf);
            }
        });
    
        final String html = "<html><head><head><body><h1>Hello, World</h1></body></html>";
        return new NanoHTTPD.Response(HTTP_OK, MIME_HTML, html);
    }
    
[/code]

の中で、パラメータの中にリクエスト元のIPアドレスがないか確認しましたが、uri,method,header,parms,filesに全てにリクエスト元IPアドレスの情報はありませんでした。

アクセス元の制限をかけるにはどのようにすればいいかご存知の方、ご教示お願いします。


CC BY-SA 3.0
2015-11-10T06:00:03.283
18611
2015-11-11T09:31:12.490
2015-11-10T08:50:33.540
7290
8593
question
android java nanohttpd
NanoHTTPD.javaでIP制限を行いたい


JavaSE環境で見た限りでは `session.getHeaders().get("remote-addr")` で取得できています。

<https://github.com/NanoHttpd/nanohttpd/blob/0f5ae0751dcaf3182ba094403debaf085b3ac58e/core/src/main/java/fi/iki/elonen/NanoHTTPD.java#L819-L820>


CC BY-SA 3.0
2015-11-10T07:26:57.613
18612
2015-11-10T07:26:57.613
2808
18611
answer


参考サイトで Override している serve メソッドは、NanoHTTPD
[v1.1](https://github.com/NanoHttpd/nanohttpd/blob/nanohttpd-for-
java1.1/NanoHTTPD.java)
のものであり、[v1.6](https://github.com/NanoHttpd/nanohttpd/blob/master/core/src/main/java/fi/iki/elonen/NanoHTTPD.java)
の serve メソッドとは互換性がありません。

1.1 では`remote-addr`情報は Header に含められていません。一方 1.6 では、`remote-addr`と`http-client-
ip`が Header に含められています。

なので、アクセス制御のためには、v1.6 を使って実現するように持って行くしかないでしょう。

1.6 には、参考サイトの

[code]

    public Response serve(String uri, String method,
        Properties header, Properties parms, Properties files)
    
[/code]

はなくなり（実際は非推奨化）、代わりに

[code]

    public Response serve(IHTTPSession session)
    
[/code]

となっています。ということで、 **yukihane さん回答済の`sesstion.getHeaders().get("remote-
addr")`を使う場合** 、`serve`メソッドを Override
して、その中で、`session`オブジェクトを利用して、リモードアドレスをチェックする処理を入れてから、親クラスの処理に渡すという形にするのがいいと思います。

[code]

    private static final CharSequence FORBIDDEN = "192.168.0.3";
    
    @Override
    public Response serve(IHTTPSession session) {
    
        String remoteAddr = session.getHeaders().get("remote-addr");
        if (remoteAddr.contains(FORBIDDEN)) {
            return newFixedLengthResponse(Response.Status.HTTP_FORBIDDEN,
                NanoHTTPD.MIME_HTML, "<p>Your are not allowed to access.</p>");
        }
    
        super.serve(session);
    }
    
[/code]


CC BY-SA 3.0
2015-11-10T08:47:46.607
18617
2015-11-11T09:31:12.490
2015-11-11T09:31:12.490
7290
7290
18611
answer


[getRemoteSocketAddress()](http://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#getRemoteSocketAddress%28%29)
を使うのはどうでしょうか。

クライアントからアクセスがあると(`HTTPSession(myServerSocket.accept());`)、スレッドが生成されて
`HTTPSession` クラスのインスタンスが作成されます。そのコンストラクタ内でアドレスのフィルタリングを行うことになるかと思います。

[code]

    /**
     * Starts a HTTP server to given port.<p>
     * Throws an IOException if the socket is already in use
     */
    public NanoHTTPD( int port, File wwwroot ) throws IOException
    {
      myTcpPort = port;
      this.myRootDir = wwwroot;
      myServerSocket = new ServerSocket( myTcpPort );
      myThread = new Thread( new Runnable()
        {
          public void run()
          {
            try
            {
              while( true )
                new HTTPSession( myServerSocket.accept());
                //  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            }
            catch ( IOException ioe )
    
                   :
    
    /**
     * Handles one session, i.e. parses the HTTP request
     * and returns the response.
     */
    private class HTTPSession implements Runnable
    {
      public HTTPSession( Socket s )
      {
        mySocket = s;
    
        // Here  
        SocketAddress remoteIPAddress = mySocket.getRemoteSocketAddress();
        System.out.println(remoteIPAddress);
        // => /192.168.0.3:49825
    
        Thread t = new Thread( this );
        t.setDaemon( true );
        t.start();
      }
    
[/code]


CC BY-SA 3.0
2015-11-10T12:30:54.093
18627
2015-11-10T12:30:54.093
18611
answer