001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.client;
018:
019: import javax.security.auth.login.FailedLoginException;
020: import java.net.URI;
021: import java.net.URISyntaxException;
022: import java.rmi.RemoteException;
023:
024: public class ClientSecurity {
025: public static final String IDENTITY_RESOLVER_STRATEGY = "openejb.client.identityResolver";
026:
027: private static ServerMetaData server;
028: private static IdentityResolver identityResolver;
029: private static Object staticClientIdentity;
030: private static InheritableThreadLocal<Object> threadClientIdentity = new InheritableThreadLocal<Object>();
031:
032: static {
033: // determine the server uri
034: String serverUri = System.getProperty("openejb.server.uri");
035:
036: if (serverUri != null) {
037: // determine the server location
038: try {
039: URI location = new URI(serverUri);
040: server = new ServerMetaData(location);
041: } catch (Exception e) {
042: if (serverUri.indexOf("://") == -1) {
043: try {
044: URI location = new URI("oejb://" + serverUri);
045: server = new ServerMetaData(location);
046: } catch (URISyntaxException ignored) {
047: }
048: }
049: }
050: }
051: }
052:
053: public static ServerMetaData getServer() {
054: return server;
055: }
056:
057: public static void setServer(ServerMetaData server) {
058: ClientSecurity.server = server;
059: }
060:
061: /**
062: * Login the spedified user using the specified password. This is a global login for the
063: * entire Java Virtural Machine. If you would like to have a thread scoped login, use
064: * ClientSecurity.login(username, password, true);
065: * </p>
066: * This is the equivalent of ClientSecurity.login(username, password, false);
067: * @param username the user to login
068: * @param password the password for the user
069: * @throws FailedLoginException if the username and password combination are not valid or
070: * if there is a problem communiating with the server
071: */
072: public static void login(String username, String password)
073: throws FailedLoginException {
074: login(username, password, false);
075: }
076:
077: /**
078: * Login the spedified user using the specified password either globally for the
079: * entire Java Virtural Machine or scoped to the thread.
080: * </p>
081: * When using thread scoped login, you should logout in a finally block. This particularly
082: * when using thread pools. If a thread is returned to the pool with a login attached to the
083: * thread the next user of that thread will inherit the thread scoped login.
084: *
085: * @param username the user to login
086: * @param password the password for the user
087: * @param threadScoped if true the login is scoped to the thread; otherwise the login is global
088: * for the entire Java Virtural Machine
089: * @throws FailedLoginException if the username and password combination are not valid or
090: * if there is a problem communiating with the server
091: */
092: public static void login(String username, String password,
093: boolean threadScoped) throws FailedLoginException {
094: Object clientIdentity = directAuthentication(username,
095: password, server);
096: if (threadScoped) {
097: threadClientIdentity.set(clientIdentity);
098: } else {
099: staticClientIdentity = clientIdentity;
100: }
101: identityResolver = new SimpleIdentityResolver();
102: }
103:
104: /**
105: * Clears the thread and global login data.
106: */
107: public static void logout() {
108: threadClientIdentity.set(null);
109: staticClientIdentity = null;
110: }
111:
112: /**
113: * This is a helper method for login modules. Directly authenticates with the server using the specified
114: * username and password returning the identity token for the client. This methods does not store the
115: * identity token and the caller must arrange for the to be available to the OpenEJB proxies via an
116: * IdentityResolver.
117: *
118: * @param username the username for authentication
119: * @param password the password for authentication
120: * @param server
121: * @return the client identity token
122: * @throws FailedLoginException if the username password combination is not valid
123: */
124: public static Object directAuthentication(String username,
125: String password, ServerMetaData server)
126: throws FailedLoginException {
127: return directAuthentication(null, username, password, server);
128: }
129:
130: public static Object directAuthentication(String securityRealm,
131: String username, String password, ServerMetaData server)
132: throws FailedLoginException {
133: // authenticate
134: AuthenticationRequest authReq = new AuthenticationRequest(
135: securityRealm, username, password);
136: AuthenticationResponse authRes;
137: try {
138: authRes = (AuthenticationResponse) Client.request(authReq,
139: new AuthenticationResponse(), server);
140: } catch (RemoteException e) {
141: throw (FailedLoginException) new FailedLoginException(
142: "Unable to authenticate with server " + server)
143: .initCause(e);
144: }
145:
146: // check the response
147: if (authRes.getResponseCode() != ResponseCodes.AUTH_GRANTED) {
148: throw (FailedLoginException) new FailedLoginException(
149: "This principal is not authenticated.")
150: .initCause(authRes.getDeniedCause());
151: }
152:
153: // return the response object
154: Object clientIdentity = authRes.getIdentity()
155: .getClientIdentity();
156: return clientIdentity;
157: }
158:
159: public static Object getIdentity() {
160: return getIdentityResolver().getIdentity();
161: }
162:
163: public static IdentityResolver getIdentityResolver() {
164: if (identityResolver == null) {
165: String strategy = System
166: .getProperty(IDENTITY_RESOLVER_STRATEGY);
167: if (strategy == null) {
168: identityResolver = new JaasIdentityResolver();
169: } else {
170: // find the strategy class
171: ResourceFinder finder = new ResourceFinder("META-INF/");
172: Class identityResolverClass;
173: try {
174: identityResolverClass = finder
175: .findClass(IdentityResolver.class.getName()
176: + "/" + strategy);
177: } catch (Exception e) {
178: throw new IllegalArgumentException(
179: "Could not find client identity strategy '"
180: + strategy + "'");
181: }
182:
183: // verify the interface
184: if (!IdentityResolver.class
185: .isAssignableFrom(identityResolverClass)) {
186: throw new IllegalArgumentException(
187: "Client identity strategy '"
188: + strategy
189: + "' "
190: + "class '"
191: + identityResolverClass.getName()
192: + "' does not implement the "
193: + "interface '"
194: + IdentityResolver.class
195: .getSimpleName() + "'");
196: }
197:
198: // create the class
199: try {
200: identityResolver = (IdentityResolver) identityResolverClass
201: .newInstance();
202: } catch (Exception e) {
203: throw new IllegalArgumentException(
204: "Unable to create client identity strategy '"
205: + strategy + "' " + "class '"
206: + identityResolverClass.getName()
207: + "'", e);
208: }
209: }
210:
211: }
212: return identityResolver;
213: }
214:
215: public static void setIdentityResolver(
216: IdentityResolver identityResolver) {
217: ClientSecurity.identityResolver = identityResolver;
218: }
219:
220: private ClientSecurity() {
221: }
222:
223: public static class SimpleIdentityResolver implements
224: IdentityResolver {
225: public Object getIdentity() {
226: Object clientIdentity = threadClientIdentity.get();
227: if (clientIdentity == null) {
228: clientIdentity = staticClientIdentity;
229: }
230: return clientIdentity;
231: }
232: }
233: }
|