38 |
|
|
39 |
package javax.security.auth.login; |
package javax.security.auth.login; |
40 |
|
|
41 |
|
import gnu.java.security.action.GetSecurityPropertyAction; |
42 |
|
|
43 |
|
import java.security.AccessController; |
44 |
|
|
45 |
|
import java.util.HashMap; |
46 |
|
import java.util.Map; |
47 |
|
|
48 |
|
import javax.security.auth.Subject; |
49 |
|
import javax.security.auth.callback.CallbackHandler; |
50 |
|
import javax.security.auth.spi.LoginModule; |
51 |
|
|
52 |
public class LoginContext |
public class LoginContext |
53 |
{ |
{ |
54 |
|
|
55 |
|
private static final String OTHER = "other"; |
56 |
|
|
57 |
|
private final String name; |
58 |
|
private final CallbackHandler cbHandler; |
59 |
|
private final Subject subject; |
60 |
|
private final AppConfigurationEntry[] entries; |
61 |
|
private final LoginModule[] modules; |
62 |
|
private final Map sharedState; |
63 |
|
|
64 |
|
public LoginContext (final String name) throws LoginException |
65 |
|
{ |
66 |
|
this (name, new Subject(), defaultHandler()); |
67 |
|
} |
68 |
|
|
69 |
|
public LoginContext (final String name, final CallbackHandler cbHandler) |
70 |
|
throws LoginException |
71 |
|
{ |
72 |
|
this (name, new Subject(), cbHandler); |
73 |
|
} |
74 |
|
|
75 |
|
public LoginContext (final String name, final Subject subject) |
76 |
|
throws LoginException |
77 |
|
{ |
78 |
|
this (name, subject, defaultHandler()); |
79 |
|
} |
80 |
|
|
81 |
|
public LoginContext (final String name, final Subject subject, |
82 |
|
final CallbackHandler cbHandler) |
83 |
|
throws LoginException |
84 |
|
{ |
85 |
|
Configuration config = Configuration.getConfig(); |
86 |
|
AppConfigurationEntry[] entries = config.getAppConfigurationEntry (name); |
87 |
|
if (entries == null) |
88 |
|
entries = config.getAppConfigurationEntry (OTHER); |
89 |
|
if (entries == null) |
90 |
|
throw new LoginException ("no configured modules for application " |
91 |
|
+ name); |
92 |
|
this.entries = entries; |
93 |
|
modules = new LoginModule[entries.length]; |
94 |
|
sharedState = new HashMap(); |
95 |
|
for (int i = 0; i < entries.length; i++) |
96 |
|
modules[i] = lookupModule (entries[i], subject, sharedState); |
97 |
|
this.name = name; |
98 |
|
this.subject = subject; |
99 |
|
this.cbHandler = cbHandler; |
100 |
|
} |
101 |
|
|
102 |
|
/** |
103 |
|
* Returns the authenticated subject, or the parameter passed to one |
104 |
|
* of the constructors. <code>null</code> is returned if the previous |
105 |
|
* login attempt failed and there was no subject provided. |
106 |
|
* |
107 |
|
* @return The subject, or null. |
108 |
|
*/ |
109 |
|
public Subject getSubject() |
110 |
|
{ |
111 |
|
return subject; |
112 |
|
} |
113 |
|
|
114 |
|
/** |
115 |
|
* Logs a subject in, using all login modules configured for this |
116 |
|
* application. This method will call the {@link LoginModule#login()} |
117 |
|
* method of each module configured for this application, stopping |
118 |
|
* if a REQUISITE module fails or if a SUFFICIENT module succeeds. If |
119 |
|
* the overall login attempt fails, a {@link LoginException} will be |
120 |
|
* thrown. |
121 |
|
* |
122 |
|
* @throws LoginException If logging in fails. |
123 |
|
*/ |
124 |
|
public void login() throws LoginException |
125 |
|
{ |
126 |
|
boolean failure = false; |
127 |
|
for (int i = 0; i < modules.length; i++) |
128 |
|
{ |
129 |
|
try |
130 |
|
{ |
131 |
|
boolean result = modules[i].login(); |
132 |
|
if (!result) |
133 |
|
{ |
134 |
|
if (entries[i].getControlFlag() == |
135 |
|
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) |
136 |
|
throw new LoginException ("REQUISITE module " + entries[i].getLoginModuleName() |
137 |
|
+ " failed"); |
138 |
|
else if (entries[i].getControlFlag() == |
139 |
|
AppConfigurationEntry.LoginModuleControlFlag.REQUIRED) |
140 |
|
failure = true; |
141 |
|
} |
142 |
|
else |
143 |
|
{ |
144 |
|
if (entries[i].getControlFlag() == |
145 |
|
AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT) |
146 |
|
break; |
147 |
|
} |
148 |
|
} |
149 |
|
catch (LoginException le) |
150 |
|
{ |
151 |
|
if (entries[i].getControlFlag() != |
152 |
|
AppConfigurationEntry.LoginModuleControlFlag.REQUISITE) |
153 |
|
continue; |
154 |
|
for (int j = 0; j < modules.length; j++) |
155 |
|
modules[i].abort(); |
156 |
|
throw le; |
157 |
|
} |
158 |
|
} |
159 |
|
if (failure) |
160 |
|
throw new LoginException ("not all REQUIRED modules succeeded"); |
161 |
|
|
162 |
|
for (int i = 0; i < modules.length; i++) |
163 |
|
modules[i].commit(); |
164 |
|
} |
165 |
|
|
166 |
|
/** |
167 |
|
* Logs a subject out, cleaning up any state that may be in memory. |
168 |
|
* |
169 |
|
* @throws LoginException If logging out fails. |
170 |
|
*/ |
171 |
|
public void logout() throws LoginException |
172 |
|
{ |
173 |
|
for (int i = 0; i < modules.length; i++) |
174 |
|
modules[i].logout(); |
175 |
|
} |
176 |
|
|
177 |
|
// Own methods. |
178 |
|
|
179 |
|
/** |
180 |
|
* Fetch the default callback handler, based on the |
181 |
|
* auth.login.defaultCallbackHandler property, or null if it is not |
182 |
|
* set. |
183 |
|
*/ |
184 |
|
private static CallbackHandler defaultHandler() |
185 |
|
{ |
186 |
|
GetSecurityPropertyAction act = |
187 |
|
new GetSecurityPropertyAction ("auth.login.defaultCallbackHandler"); |
188 |
|
String classname = (String) AccessController.doPrivileged (act); |
189 |
|
if (classname != null) |
190 |
|
{ |
191 |
|
try |
192 |
|
{ |
193 |
|
return (CallbackHandler) Class.forName (classname).newInstance(); |
194 |
|
} |
195 |
|
catch (ClassNotFoundException cnfe) |
196 |
|
{ |
197 |
|
return null; |
198 |
|
} |
199 |
|
catch (ClassCastException cce) |
200 |
|
{ |
201 |
|
return null; |
202 |
|
} |
203 |
|
catch (IllegalAccessException iae) |
204 |
|
{ |
205 |
|
return null; |
206 |
|
} |
207 |
|
catch (InstantiationException ie) |
208 |
|
{ |
209 |
|
return null; |
210 |
|
} |
211 |
|
} |
212 |
|
return null; |
213 |
|
} |
214 |
|
|
215 |
|
private LoginModule lookupModule (AppConfigurationEntry entry, |
216 |
|
Subject subject, Map sharedState) |
217 |
|
throws LoginException |
218 |
|
{ |
219 |
|
LoginModule module = null; |
220 |
|
Exception cause = null; |
221 |
|
try |
222 |
|
{ |
223 |
|
module = (LoginModule) Class.forName (entry.getLoginModuleName()).newInstance(); |
224 |
|
} |
225 |
|
catch (ClassNotFoundException cnfe) |
226 |
|
{ |
227 |
|
cause = cnfe; |
228 |
|
} |
229 |
|
catch (ClassCastException cce) |
230 |
|
{ |
231 |
|
cause = cce; |
232 |
|
} |
233 |
|
catch (IllegalAccessException iae) |
234 |
|
{ |
235 |
|
cause = iae; |
236 |
|
} |
237 |
|
catch (InstantiationException ie) |
238 |
|
{ |
239 |
|
cause = ie; |
240 |
|
} |
241 |
|
|
242 |
|
if (cause != null) |
243 |
|
{ |
244 |
|
LoginException le = new LoginException ("could not load module " |
245 |
|
+ entry.getLoginModuleName()); |
246 |
|
le.initCause (cause); |
247 |
|
throw le; |
248 |
|
} |
249 |
|
|
250 |
|
module.initialize (subject, cbHandler, sharedState, entry.getOptions()); |
251 |
|
return module; |
252 |
|
} |
253 |
} |
} |