PageRenderTime 25ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/JAASLoginService.java

https://github.com/dekellum/jetty
Java | 310 lines | 202 code | 36 blank | 72 comment | 14 complexity | bb181379f86b8b3612960fa85c795145 MD5 | raw file
  1. // ========================================================================
  2. // Copyright (c) 2003-2009 Mort Bay Consulting Pty. Ltd.
  3. // ------------------------------------------------------------------------
  4. // All rights reserved. This program and the accompanying materials
  5. // are made available under the terms of the Eclipse Public License v1.0
  6. // and Apache License v2.0 which accompanies this distribution.
  7. // The Eclipse Public License is available at
  8. // http://www.eclipse.org/legal/epl-v10.html
  9. // The Apache License v2.0 is available at
  10. // http://www.opensource.org/licenses/apache2.0.php
  11. // You may elect to redistribute this code under either of these licenses.
  12. // ========================================================================
  13. package org.eclipse.jetty.plus.jaas;
  14. import java.io.IOException;
  15. import java.security.Principal;
  16. import java.util.ArrayList;
  17. import java.util.Arrays;
  18. import java.util.Collection;
  19. import java.util.LinkedHashSet;
  20. import java.util.Set;
  21. import javax.security.auth.Subject;
  22. import javax.security.auth.callback.Callback;
  23. import javax.security.auth.callback.CallbackHandler;
  24. import javax.security.auth.callback.NameCallback;
  25. import javax.security.auth.callback.PasswordCallback;
  26. import javax.security.auth.callback.UnsupportedCallbackException;
  27. import javax.security.auth.login.LoginContext;
  28. import javax.security.auth.login.LoginException;
  29. import org.eclipse.jetty.plus.jaas.callback.ObjectCallback;
  30. import org.eclipse.jetty.security.DefaultIdentityService;
  31. import org.eclipse.jetty.security.IdentityService;
  32. import org.eclipse.jetty.security.LoginService;
  33. import org.eclipse.jetty.server.UserIdentity;
  34. import org.eclipse.jetty.util.Loader;
  35. import org.eclipse.jetty.util.component.AbstractLifeCycle;
  36. import org.eclipse.jetty.util.log.Log;
  37. import org.eclipse.jetty.util.log.Logger;
  38. /* ---------------------------------------------------- */
  39. /** JAASLoginService
  40. *
  41. * @org.apache.xbean.XBean element="jaasUserRealm" description="Creates a UserRealm suitable for use with JAAS"
  42. */
  43. public class JAASLoginService extends AbstractLifeCycle implements LoginService
  44. {
  45. private static final Logger LOG = Log.getLogger(JAASLoginService.class);
  46. public static String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.plus.jaas.JAASRole";
  47. public static String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
  48. protected String[] _roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
  49. protected String _callbackHandlerClass;
  50. protected String _realmName;
  51. protected String _loginModuleName;
  52. protected JAASUserPrincipal _defaultUser = new JAASUserPrincipal(null, null, null);
  53. protected IdentityService _identityService;
  54. /* ---------------------------------------------------- */
  55. /**
  56. * Constructor.
  57. *
  58. */
  59. public JAASLoginService()
  60. {
  61. }
  62. /* ---------------------------------------------------- */
  63. /**
  64. * Constructor.
  65. *
  66. * @param name the name of the realm
  67. */
  68. public JAASLoginService(String name)
  69. {
  70. this();
  71. _realmName = name;
  72. _loginModuleName = name;
  73. }
  74. /* ---------------------------------------------------- */
  75. /**
  76. * Get the name of the realm.
  77. *
  78. * @return name or null if not set.
  79. */
  80. public String getName()
  81. {
  82. return _realmName;
  83. }
  84. /* ---------------------------------------------------- */
  85. /**
  86. * Set the name of the realm
  87. *
  88. * @param name a <code>String</code> value
  89. */
  90. public void setName (String name)
  91. {
  92. _realmName = name;
  93. }
  94. /* ------------------------------------------------------------ */
  95. /** Get the identityService.
  96. * @return the identityService
  97. */
  98. public IdentityService getIdentityService()
  99. {
  100. return _identityService;
  101. }
  102. /* ------------------------------------------------------------ */
  103. /** Set the identityService.
  104. * @param identityService the identityService to set
  105. */
  106. public void setIdentityService(IdentityService identityService)
  107. {
  108. _identityService = identityService;
  109. }
  110. /* ------------------------------------------------------------ */
  111. /**
  112. * Set the name to use to index into the config
  113. * file of LoginModules.
  114. *
  115. * @param name a <code>String</code> value
  116. */
  117. public void setLoginModuleName (String name)
  118. {
  119. _loginModuleName = name;
  120. }
  121. /* ------------------------------------------------------------ */
  122. public void setCallbackHandlerClass (String classname)
  123. {
  124. _callbackHandlerClass = classname;
  125. }
  126. /* ------------------------------------------------------------ */
  127. public void setRoleClassNames (String[] classnames)
  128. {
  129. ArrayList<String> tmp = new ArrayList<String>();
  130. if (classnames != null)
  131. tmp.addAll(Arrays.asList(classnames));
  132. if (!tmp.contains(DEFAULT_ROLE_CLASS_NAME))
  133. tmp.add(DEFAULT_ROLE_CLASS_NAME);
  134. _roleClassNames = tmp.toArray(new String[tmp.size()]);
  135. }
  136. /* ------------------------------------------------------------ */
  137. public String[] getRoleClassNames()
  138. {
  139. return _roleClassNames;
  140. }
  141. /* ------------------------------------------------------------ */
  142. /**
  143. * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
  144. */
  145. protected void doStart() throws Exception
  146. {
  147. if (_identityService==null)
  148. _identityService=new DefaultIdentityService();
  149. super.doStart();
  150. }
  151. /* ------------------------------------------------------------ */
  152. public UserIdentity login(final String username,final Object credentials)
  153. {
  154. try
  155. {
  156. CallbackHandler callbackHandler = null;
  157. if (_callbackHandlerClass == null)
  158. {
  159. callbackHandler = new CallbackHandler()
  160. {
  161. public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
  162. {
  163. for (Callback callback: callbacks)
  164. {
  165. if (callback instanceof NameCallback)
  166. {
  167. ((NameCallback)callback).setName(username);
  168. }
  169. else if (callback instanceof PasswordCallback)
  170. {
  171. ((PasswordCallback)callback).setPassword((char[]) credentials.toString().toCharArray());
  172. }
  173. else if (callback instanceof ObjectCallback)
  174. {
  175. ((ObjectCallback)callback).setObject(credentials);
  176. }
  177. }
  178. }
  179. };
  180. }
  181. else
  182. {
  183. Class clazz = Loader.loadClass(getClass(), _callbackHandlerClass);
  184. callbackHandler = (CallbackHandler)clazz.newInstance();
  185. }
  186. //set up the login context
  187. //TODO jaspi requires we provide the Configuration parameter
  188. Subject subject = new Subject();
  189. LoginContext loginContext = new LoginContext(_loginModuleName, subject, callbackHandler);
  190. loginContext.login();
  191. //login success
  192. JAASUserPrincipal userPrincipal = new JAASUserPrincipal(getUserName(callbackHandler), subject, loginContext);
  193. subject.getPrincipals().add(userPrincipal);
  194. return _identityService.newUserIdentity(subject,userPrincipal,getGroups(subject));
  195. }
  196. catch (LoginException e)
  197. {
  198. LOG.warn(e);
  199. }
  200. catch (IOException e)
  201. {
  202. LOG.warn(e);
  203. }
  204. catch (UnsupportedCallbackException e)
  205. {
  206. LOG.warn(e);
  207. }
  208. catch (InstantiationException e)
  209. {
  210. LOG.warn(e);
  211. }
  212. catch (IllegalAccessException e)
  213. {
  214. LOG.warn(e);
  215. }
  216. catch (ClassNotFoundException e)
  217. {
  218. LOG.warn(e);
  219. }
  220. return null;
  221. }
  222. /* ------------------------------------------------------------ */
  223. public boolean validate(UserIdentity user)
  224. {
  225. // TODO optionally check user is still valid
  226. return true;
  227. }
  228. /* ------------------------------------------------------------ */
  229. private String getUserName(CallbackHandler callbackHandler) throws IOException, UnsupportedCallbackException
  230. {
  231. NameCallback nameCallback = new NameCallback("foo");
  232. callbackHandler.handle(new Callback[] {nameCallback});
  233. return nameCallback.getName();
  234. }
  235. /* ------------------------------------------------------------ */
  236. public void logout(UserIdentity user)
  237. {
  238. Set<JAASUserPrincipal> userPrincipals = user.getSubject().getPrincipals(JAASUserPrincipal.class);
  239. LoginContext loginContext = userPrincipals.iterator().next().getLoginContext();
  240. try
  241. {
  242. loginContext.logout();
  243. }
  244. catch (LoginException e)
  245. {
  246. LOG.warn(e);
  247. }
  248. }
  249. /* ------------------------------------------------------------ */
  250. @SuppressWarnings({ "unchecked", "rawtypes" })
  251. private String[] getGroups (Subject subject)
  252. {
  253. //get all the roles of the various types
  254. String[] roleClassNames = getRoleClassNames();
  255. Collection<String> groups = new LinkedHashSet<String>();
  256. try
  257. {
  258. for (String roleClassName : roleClassNames)
  259. {
  260. Class load_class = Thread.currentThread().getContextClassLoader().loadClass(roleClassName);
  261. Set<Principal> rolesForType = subject.getPrincipals(load_class);
  262. for (Principal principal : rolesForType)
  263. {
  264. groups.add(principal.getName());
  265. }
  266. }
  267. return groups.toArray(new String[groups.size()]);
  268. }
  269. catch (ClassNotFoundException e)
  270. {
  271. throw new RuntimeException(e);
  272. }
  273. }
  274. }