11 February 2014

Java server Authentication based on Cookies

Here is Java server Authentication based on cookies. You provide four routes (contexts):

  • general ("/"), containg the HTML login POST form;
  • "/login" to log in (POST method only);
  • "/logout" to log out (POST and GET methods);
  • protected route "/conf" to get confidential information.

You also provide the isLogged method to check if the access is granted for specific routes - in this case, the "/conf" route.

In the example below, the username and password are both "admin", which expires in 1 minute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import java.io.*;
import java.util.*;
import com.sun.net.httpserver.*;

public class httpserver {

  public static void main(String[] args) throws Exception {
    HttpServer server = HttpServer.create(new java.net.InetSocketAddress(8080), 0);
    server.createContext("/", new info());
    server.createContext("/login", new login());
    server.createContext("/logout", new logout());
    server.createContext("/conf", new protectedInfo());
    server.createContext("/res", new serveFile());
    server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
    // or Executors.newFixedThreadPool(10), or NULL if no threadings
    server.start();
    System.out.println("> Server running on PORT: 8080...");
  }

  static class serveFile implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {
        String fileName = t.getRequestURI().getPath().substring(5);
        System.out.println("File Name: [" + fileName + ']');
        File file = new File(fileName);
        if (!file.exists() || !file.isFile()) { respond(t, "File ["+ fileName +"] not found or not a file.", "text", null); return; }
        t.getResponseHeaders().set("Content-Type", getExtension(fileName));
        t.sendResponseHeaders(200, 0);
        OutputStream out = t.getResponseBody();
        FileInputStream fs = new FileInputStream(file);
        final byte[] buffer = new byte[1024];
        int count = 0;
        while((count = fs.read(buffer)) >= 0) out.write(buffer, 0, count);
        out.flush();
        out.close();
        fs.close();
    }
  }

  static class login implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {
      if(t.getRequestMethod().equals("POST")) {
        Map<String,String> cred = mapQueries(getBody(t));
        if(cred != null) {
          String user = cred.get("user"), pass = cred.get("pass");
          if(user != null && pass != null) {
            if(user.equals("admin") && pass.equals("admin")) {
              respond(t, "Login successful.", "text", "user=admin; Max-Age=60");
              return;
            }
          }
        }
      }
      respond(t, "Wrong login.", "text", null);
    }
  }

  static class logout implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {
      respond(t, "You logged out.", "text", "user=?; Max-Age=-1");
    }
  }

  static class protectedInfo implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {
      if(!isLogged(t)) { respond(t, "UNAUTHORISED!", "text", null); return; }
      respond(t, "Protected information is here.", "text", null);
    }
  }

  static class info implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {
      String RES = "<html><body>";

      RES += "<form action='/' method='GET'>";
      RES += "<input type='text' name='issue' value='Check string for tests.'/>";
      RES += "<input type='text' name='answer' value='Another check string.'/>";
      RES += "<input type='submit' value='Submit (get)'/>";
      RES += "</form><br>";

      RES += "<form action='/login' method='POST'>";
      RES += "<input type='text' name='user' value='admin'/>";
      RES += "<input type='password' name='pass' value='admin'/>";
      RES += "<input type='submit' value='Login'/>";
      RES += "</form><br>";

      RES += "<table style='font:normal 10pt sans-serif;'>";
      RES += "<tr><td bgColor='#ff8'>URI/path:</td><td>" + t.getRequestURI().getPath() + "</td></tr>";
      RES += "<tr><td bgColor='#ff8'>PROTOCOL:</td><td>" + t.getProtocol() + "</td></tr>";
      RES += "<tr><td bgColor='#ff8'>METHOD:</td><td>" + t.getRequestMethod() + "</td></tr>";

      RES += "<tr bgColor='#8f8'><td>QUERIES:</td><td></td></tr>";
      Map<String,String> q = mapQueries(t.getRequestURI().getQuery());
      if(q != null) {
        for(Map.Entry<String,String> el : q.entrySet())
        RES += "<tr><td bgColor='#ff8'><b>"+el.getKey()+"</b></td><td>" + el.getValue() + "</td></tr>";
      }

      RES += "<tr bgColor='#8f8'><td>HEADERS:</td><td></td></tr>";
      Headers hs = t.getRequestHeaders();
      for(Map.Entry<String, List<String>> h : hs.entrySet())
        RES += "<tr><td bgColor='#ff8'>"+h.getKey()+"</td><td>" + h.getValue().get(0) + "</td></tr>";

      RES += "</table></body></html>";
      respond(t, RES, "html", null);
    }
  }

  static void respond(HttpExchange t, String Res, String type, String cookie) throws IOException {

    Headers h = t.getResponseHeaders();
    h.set("Content-Type", "text/" + type);
    if(cookie != null) h.set("Set-Cookie", cookie);
    t.sendResponseHeaders(200, Res.length());
    OutputStream os = t.getResponseBody();
    os.write(Res.getBytes());
    os.close();
  }

  static Map<String,String> mapQueries(String q) {
    if(q == null) return null;
    String[] arr = q.split("&");
    Map<String, String> data = new HashMap<String, String>();
    try {
      for(int i=0; i<arr.length; i++) {
        int ix = arr[i].indexOf('='); if(ix<0) return null;
        data.put(arr[i].substring(0, ix), java.net.URLDecoder.decode(arr[i].substring(ix+1), "UTF-8"));
      }
    } catch(UnsupportedEncodingException ex) { return null; }
    return data;
  }

  static String getBody(HttpExchange t) {
    StringBuilder st = new StringBuilder();
    new BufferedReader(new InputStreamReader(t.getRequestBody()))
      .lines().forEach((String s)->st.append(s));
    return st.toString();
  }

  static boolean isLogged(HttpExchange t) {
    List<String> coo = t.getRequestHeaders().get("Cookie");
    if(coo == null) return false;
    if("user=admin".equals(coo.get(0))) return true;
    return false;
  }

  static String getFileName(String path) {
    return path.substring(path.lastIndexOf('/') + 1);
  }

  static String getExtension(String fileName) {
    int ix = fileName.lastIndexOf('.');
    if(ix < 0 ) return "text/plain";
    String ext = fileName.substring(ix);
    if(".css.html.htm.".contains(ext)) return "text/" + ext.substring(1);
    if(".js".equals(ext)) return "text/javascript";
    if(".ico".equals(ext)) return "image/x-icon";
    if(".svg".equals(ext)) return "image/svg+xml";
    if(".jpg.jpeg.jfif.pjpeg.pjp".contains(ext)) return "image/jpeg";
    if(".png.gif.bmp.webp.tiff".contains(ext)) return "image/" + ext.substring(1);
    if(".xml.pdf.zip.".contains(ext)) return "application/" + ext.substring(1);
    return "text/plain";
  }
}

No comments:

Post a Comment