src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java
changeset 57838 78844dceede6
parent 47216 71c04702a3d5
equal deleted inserted replaced
57837:2227a0cfd6b3 57838:78844dceede6
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package com.sun.net.httpserver;
    26 package com.sun.net.httpserver;
    27 
    27 
       
    28 import java.nio.charset.Charset;
    28 import java.util.Base64;
    29 import java.util.Base64;
       
    30 import java.util.Objects;
       
    31 
       
    32 import static java.nio.charset.StandardCharsets.UTF_8;
    29 
    33 
    30 /**
    34 /**
    31  * BasicAuthenticator provides an implementation of HTTP Basic
    35  * BasicAuthenticator provides an implementation of HTTP Basic
    32  * authentication. It is an abstract class and must be extended
    36  * authentication. It is an abstract class and must be extended
    33  * to provide an implementation of {@link #checkCredentials(String,String)}
    37  * to provide an implementation of {@link #checkCredentials(String,String)}
    34  * which is called to verify each incoming request.
    38  * which is called to verify each incoming request.
    35  */
    39  */
    36 public abstract class BasicAuthenticator extends Authenticator {
    40 public abstract class BasicAuthenticator extends Authenticator {
    37 
    41 
    38     protected String realm;
    42     protected final String realm;
       
    43     protected final Charset charset;
       
    44     private final boolean isUTF8;
    39 
    45 
    40     /**
    46     /**
    41      * Creates a BasicAuthenticator for the given HTTP realm
    47      * Creates a BasicAuthenticator for the given HTTP realm.
       
    48      * The Basic authentication credentials (username and password) are decoded
       
    49      * using the platform's {@link Charset#defaultCharset() default character set}.
       
    50      *
    42      * @param realm The HTTP Basic authentication realm
    51      * @param realm The HTTP Basic authentication realm
    43      * @throws NullPointerException if the realm is an empty string
    52      * @throws NullPointerException if realm is {@code null}
       
    53      * @throws IllegalArgumentException if realm is an empty string
    44      */
    54      */
    45     public BasicAuthenticator (String realm) {
    55     public BasicAuthenticator (String realm) {
       
    56         this(realm, Charset.defaultCharset());
       
    57     }
       
    58 
       
    59     /**
       
    60      * Creates a BasicAuthenticator for the given HTTP realm and using the
       
    61      * given {@link Charset} to decode the Basic authentication credentials
       
    62      * (username and password).
       
    63      *
       
    64      * @apiNote {@code UTF-8} is the recommended charset because its usage is
       
    65      * communicated to the client, and therefore more likely to be used also
       
    66      * by the client.
       
    67      *
       
    68      * @param realm The HTTP Basic authentication realm
       
    69      * @param charset The Charset to decode incoming credentials from the client
       
    70      * @throws NullPointerException if realm or charset are {@code null}
       
    71      * @throws IllegalArgumentException if realm is an empty string
       
    72      */
       
    73     public BasicAuthenticator (String realm, Charset charset) {
       
    74         Objects.requireNonNull(charset);
       
    75         if (realm.isEmpty()) // implicit NPE check
       
    76             throw new IllegalArgumentException("realm must not be empty");
    46         this.realm = realm;
    77         this.realm = realm;
       
    78         this.charset = charset;
       
    79         this.isUTF8 = charset.equals(UTF_8);
    47     }
    80     }
    48 
    81 
    49     /**
    82     /**
    50      * returns the realm this BasicAuthenticator was created with
    83      * returns the realm this BasicAuthenticator was created with
    51      * @return the authenticator's realm string.
    84      * @return the authenticator's realm string.
    61          * look for auth token
    94          * look for auth token
    62          */
    95          */
    63         String auth = rmap.getFirst ("Authorization");
    96         String auth = rmap.getFirst ("Authorization");
    64         if (auth == null) {
    97         if (auth == null) {
    65             Headers map = t.getResponseHeaders();
    98             Headers map = t.getResponseHeaders();
    66             map.set ("WWW-Authenticate", "Basic realm=" + "\""+realm+"\"");
    99             var authString = "Basic realm=" + "\"" + realm + "\"" +
       
   100                 (isUTF8 ? " charset=\"UTF-8\"" : "");
       
   101             map.set ("WWW-Authenticate", authString);
    67             return new Authenticator.Retry (401);
   102             return new Authenticator.Retry (401);
    68         }
   103         }
    69         int sp = auth.indexOf (' ');
   104         int sp = auth.indexOf (' ');
    70         if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) {
   105         if (sp == -1 || !auth.substring(0, sp).equals ("Basic")) {
    71             return new Authenticator.Failure (401);
   106             return new Authenticator.Failure (401);
    72         }
   107         }
    73         byte[] b = Base64.getDecoder().decode(auth.substring(sp+1));
   108         byte[] b = Base64.getDecoder().decode(auth.substring(sp+1));
    74         String userpass = new String (b);
   109         String userpass = new String (b, charset);
    75         int colon = userpass.indexOf (':');
   110         int colon = userpass.indexOf (':');
    76         String uname = userpass.substring (0, colon);
   111         String uname = userpass.substring (0, colon);
    77         String pass = userpass.substring (colon+1);
   112         String pass = userpass.substring (colon+1);
    78 
   113 
    79         if (checkCredentials (uname, pass)) {
   114         if (checkCredentials (uname, pass)) {