View Javadoc

1   package com.bradmcevoy.http;
2   
3   import com.bradmcevoy.common.StringSplitUtils;
4   import java.util.Map;
5   import org.apache.commons.codec.binary.Base64;
6   import org.slf4j.Logger;
7   import org.slf4j.LoggerFactory;
8   
9   /**
10   * Holds authentication information for a request
11   *
12   * There are two sets of information:
13   *   - that which is present in the request
14   *   - that which is determined as part of performing authentication
15   *
16   * Note that even if authentication fails, this object will still be available
17   * in the request - DO NOT USE THE PRESENCE OF THIS OBJECT TO CHECK FOR A VALID LOGIN!!!
18   *
19   * Instead use the tag property. This will ONLY be not null after a successful
20   * authentication
21   *
22   * @author brad
23   */
24  public class Auth {
25  
26      private static final Logger log = LoggerFactory.getLogger( Auth.class );
27  
28      /**
29       * Holds application specific user data, as returned from the authenticate
30       * method on Resource
31       *
32       * This should be used to test for a valid login.
33       */
34      private Object tag;
35  
36      /**
37       * Common HTTP authentication schemes, and some non-http specified but common
38       * ones
39       */
40      public enum Scheme {
41          BASIC,
42          DIGEST,
43          NEGOTIATE,
44          FORM,
45          SESSION
46      };
47      private Scheme scheme;
48      private String user;
49      private String password;
50  
51      private String realm;
52      private String nonce;
53      private String uri;
54      private String responseDigest;
55      private String qop;
56      private String nc;
57      private String cnonce;
58      private boolean nonceStale; // set by digest auth handler
59  
60  
61      public Auth( String sAuth ) {
62  //        log.debug( "parse: " + sAuth);
63          int pos = sAuth.indexOf( " " );
64          String schemeCode;
65          String enc;
66          if( pos >= 0 ) {
67              schemeCode = sAuth.substring( 0, pos );
68              scheme = Scheme.valueOf( schemeCode.toUpperCase() );
69              enc = sAuth.substring( pos + 1 );
70          } else {
71              // assume basic
72              scheme = Scheme.BASIC;
73              enc = sAuth;
74          }
75          if( scheme.equals( Scheme.BASIC ) ) {
76              parseBasic( enc );
77          } else if( scheme.equals( Scheme.DIGEST ) ) {
78              parseDigest( enc );
79          }
80      }
81  
82      public Auth( String user, Object userTag ) {
83          this.scheme = Scheme.BASIC;
84          this.user = user;
85          this.password = null;
86          this.tag = userTag;
87      }
88  
89      public Auth( Scheme scheme, String user, Object userTag ) {
90          this.scheme = scheme;
91          this.user = user;
92          this.password = null;
93          this.tag = userTag;
94      }
95  
96  
97      /**
98       *
99       * @return - the user property in the request. This MIGHT NOT be an
100      * actual user
101      */
102     public String getUser() {
103         return user;
104     }
105 
106     /**
107      * Set after a successful authenticate method with a not-null value
108      *
109      * The actual value will be application dependent
110      */
111     public void setTag( Object authTag ) {
112         tag = authTag;
113     }
114 
115     /**
116      * Holds application specific user data, as returned from the authenticate
117      * method on Resource
118      *
119      * This should be used to test for a valid login.
120      */
121     public Object getTag() {
122         return tag;
123     }
124 
125     public String getPassword() {
126         return password;
127     }
128 
129     public Scheme getScheme() {
130         return scheme;
131     }
132 
133     public String getCnonce() {
134         return cnonce;
135     }
136 
137     public String getNc() {
138         return nc;
139     }
140 
141     public String getNonce() {
142         return nonce;
143     }
144 
145     public String getQop() {
146         return qop;
147     }
148 
149     public String getRealm() {
150         return realm;
151     }
152 
153     public String getResponseDigest() {
154         return responseDigest;
155     }
156 
157     public String getUri() {
158         return uri;
159     }
160 
161     public boolean isNonceStale() {
162         return nonceStale;
163     }
164 
165     /**
166      * set by digest auth processing. Used to add stale nonce flag to challenge
167      * 
168      * @param nonceStale
169      */
170     public void setNonceStale( boolean nonceStale ) {
171         this.nonceStale = nonceStale;
172     }
173 
174 
175     
176 
177 
178 
179 
180     private void parseBasic( String enc ) {
181         byte[] bytes = Base64.decodeBase64( enc.getBytes() );
182         String s = new String( bytes );
183         int pos = s.indexOf( ":" );
184         if( pos >= 0 ) {
185             user = s.substring( 0, pos );
186             password = s.substring( pos + 1 );
187         } else {
188             user = s;
189             password = null;
190         }
191     }
192 
193     private void parseDigest( String s ) {
194         String[] headerEntries = StringSplitUtils.splitIgnoringQuotes( s, ',' );
195         Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap( headerEntries, "=", "\"" );
196 
197 //        log.debug( "headerMap: " + headerMap);
198 
199         user = (String) headerMap.get( "username" );
200         realm = (String) headerMap.get( "realm" );
201         nonce = (String) headerMap.get( "nonce" );
202         uri = (String) headerMap.get( "uri" );
203         responseDigest = (String) headerMap.get( "response" );
204         qop = (String) headerMap.get( "qop" ); // RFC 2617 extension
205         nc = (String) headerMap.get( "nc" ); // RFC 2617 extension
206         cnonce = (String) headerMap.get( "cnonce" ); // RFC 2617 extension
207     }
208 
209     @Override
210     public String toString() {
211         return "scheme: " + scheme + " user:" + user + " tag:" + tag;
212     }
213 
214 
215 
216 }