Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
69ea8877f3
|
@ -179,7 +179,6 @@ To allow the greatest degree of flexibility in using JAAS with web applications,
|
|||
Note that you don't ordinarily need to set these explicitly, as Jetty has defaults which will work in 99% of cases.
|
||||
However, should you need to, you can configure:
|
||||
|
||||
* a policy for role-based authorization (Default: `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`)
|
||||
* a CallbackHandler (Default: `org.eclipse.jetty.jaas.callback.DefaultCallbackHandler`)
|
||||
* a list of classnames for the Principal implementation that equate to a user role (Default: `org.eclipse.jetty.jaas.JAASRole`)
|
||||
|
||||
|
@ -190,9 +189,6 @@ Here's an example of setting each of these (to their default values):
|
|||
<New class="org.eclipse.jetty.jaas.JAASLoginService">
|
||||
<Set name="Name">Test JAAS Realm</Set>
|
||||
<Set name="LoginModuleName">xyz</Set>
|
||||
<Set name="RoleCheckPolicy">
|
||||
<New class="org.eclipse.jetty.jaas.StrictRoleCheckPolicy"/>
|
||||
</Set>
|
||||
<Set name="CallbackHandlerClass">
|
||||
org.eclipse.jetty.jaas.callback.DefaultCallbackHandler
|
||||
</Set>
|
||||
|
@ -204,16 +200,6 @@ Here's an example of setting each of these (to their default values):
|
|||
</New>
|
||||
----
|
||||
|
||||
===== RoleCheckPolicy
|
||||
|
||||
The `RoleCheckPolicy` must be an implementation of the `org.eclipse.jetty.jaas.RoleCheckPolicy` interface and its purpose is to help answer the question "is User X in Role Y" for role-based authorization requests.
|
||||
The default implementation distributed with Jetty is the `org.eclipse.jetty.jaas.StrictRoleCheckPolicy`, which will assess a user as having a particular role if that role is at the top of the stack of roles that have been temporarily pushed onto the user.
|
||||
If the user has no temporarily assigned roles, the role is amongst those configured for the user.
|
||||
|
||||
Roles can be temporarily assigned to a user programmatically by using the `pushRole(String rolename)` method of the `org.eclipse.jetty.jaas.JAASUserPrincipal` class.
|
||||
|
||||
For the majority of webapps, the default `StrictRoleCheckPolicy` will be quite adequate, however you may provide your own implementation and set it on your `JAASLoginService` instance.
|
||||
|
||||
===== CallbackHandler
|
||||
|
||||
A CallbackHandler is responsible for interfacing with the user to obtain usernames and credentials to be authenticated.
|
||||
|
|
|
@ -33,6 +33,20 @@ import static java.lang.Long.MAX_VALUE;
|
|||
* <p>Subclasses should implement {@link #onTimeoutExpired()}.</p>
|
||||
* <p>This implementation is optimised assuming that the timeout
|
||||
* will mostly be cancelled and then reused with a similar value.</p>
|
||||
* <p>This implementation has a {@link Timeout} holding the time
|
||||
* at which the scheduled task should fire, and a linked list of
|
||||
* {@link Wakeup}, each holding the actual scheduled task.</p>
|
||||
* <p>Calling {@link #schedule(long, TimeUnit)} the first time will
|
||||
* create a Timeout with an associated Wakeup and submit a task to
|
||||
* the scheduler.
|
||||
* Calling {@link #schedule(long, TimeUnit)} again with the same or
|
||||
* a larger delay will cancel the previous Timeout, but keep the
|
||||
* previous Wakeup without submitting a new task to the scheduler,
|
||||
* therefore reducing the pressure on the scheduler and avoid it
|
||||
* becomes a bottleneck.
|
||||
* When the Wakeup task fires, it will see that the Timeout is now
|
||||
* in the future and will attach a new Wakeup with the future time
|
||||
* to the Timeout, and submit a scheduler task for the new Wakeup.</p>
|
||||
*/
|
||||
public abstract class CyclicTimeout implements Destroyable
|
||||
{
|
||||
|
@ -59,24 +73,24 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
}
|
||||
|
||||
/**
|
||||
* Schedules a timeout, even if already set, cancelled or expired.
|
||||
* <p>Schedules a timeout, even if already set, cancelled or expired.</p>
|
||||
* <p>If a timeout is already set, it will be cancelled and replaced
|
||||
* by the new one.</p>
|
||||
*
|
||||
* @param delay The period of time before the timeout expires.
|
||||
* @param units The unit of time of the period.
|
||||
* @return true if the timer was already set.
|
||||
* @return true if the timeout was already set.
|
||||
*/
|
||||
public boolean schedule(long delay, TimeUnit units)
|
||||
{
|
||||
long now = System.nanoTime();
|
||||
long new_timeout_at = now + units.toNanos(delay);
|
||||
|
||||
Wakeup new_wakeup = null;
|
||||
boolean result;
|
||||
Wakeup new_wakeup;
|
||||
while (true)
|
||||
{
|
||||
Timeout timeout = _timeout.get();
|
||||
|
||||
new_wakeup = null;
|
||||
result = timeout._at != MAX_VALUE;
|
||||
|
||||
// Is the current wakeup good to use? ie before our timeout time?
|
||||
|
@ -114,14 +128,12 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
public boolean cancel()
|
||||
{
|
||||
boolean result;
|
||||
Timeout timeout;
|
||||
Timeout new_timeout;
|
||||
while (true)
|
||||
{
|
||||
timeout = _timeout.get();
|
||||
Timeout timeout = _timeout.get();
|
||||
result = timeout._at != MAX_VALUE;
|
||||
Wakeup wakeup = timeout._wakeup;
|
||||
new_timeout = wakeup == null ? NOT_SET : new Timeout(MAX_VALUE, wakeup);
|
||||
Timeout new_timeout = wakeup == null ? NOT_SET : new Timeout(MAX_VALUE, wakeup);
|
||||
if (_timeout.compareAndSet(timeout, new_timeout))
|
||||
break;
|
||||
}
|
||||
|
@ -166,7 +178,11 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x:%d,%s", getClass().getSimpleName(), hashCode(), _at, _wakeup);
|
||||
return String.format("%s@%x:%dms,%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
TimeUnit.NANOSECONDS.toMillis(_at - System.nanoTime()),
|
||||
_wakeup);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,10 +216,9 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public void run()
|
||||
{
|
||||
long now;
|
||||
Wakeup new_wakeup;
|
||||
boolean has_expired;
|
||||
|
||||
long now = System.nanoTime();
|
||||
Wakeup new_wakeup = null;
|
||||
boolean has_expired = false;
|
||||
while (true)
|
||||
{
|
||||
Timeout timeout = _timeout.get();
|
||||
|
@ -226,16 +241,12 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
// Not found, we become a noop.
|
||||
return;
|
||||
|
||||
now = System.nanoTime();
|
||||
new_wakeup = null;
|
||||
has_expired = false;
|
||||
Timeout new_timeout;
|
||||
|
||||
// We are in the wakeup list! So we have to act and we know our
|
||||
// tail has not expired (else it would have removed us from the list).
|
||||
// Remove ourselves (and any prior Wakeup) from the wakeup list.
|
||||
wakeup = wakeup._next;
|
||||
|
||||
Timeout new_timeout;
|
||||
if (timeout._at <= now)
|
||||
{
|
||||
// We have timed out!
|
||||
|
@ -274,7 +285,11 @@ public abstract class CyclicTimeout implements Destroyable
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x:%d->%s", getClass().getSimpleName(), hashCode(), _at, _next);
|
||||
return String.format("%s@%x:%dms->%s",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_at == MAX_VALUE ? _at : TimeUnit.NANOSECONDS.toMillis(_at - System.nanoTime()),
|
||||
_next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
public class JAASGroup implements Group
|
||||
{
|
||||
public static final String ROLES = "__roles__";
|
||||
|
||||
private String _name = null;
|
||||
private HashSet<Principal> _members = null;
|
||||
|
||||
public JAASGroup(String n)
|
||||
{
|
||||
this._name = n;
|
||||
this._members = new HashSet<Principal>();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public synchronized boolean addMember(Principal principal)
|
||||
{
|
||||
return _members.add(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean removeMember(Principal principal)
|
||||
{
|
||||
return _members.remove(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMember(Principal principal)
|
||||
{
|
||||
return _members.contains(principal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<? extends Principal> members()
|
||||
{
|
||||
|
||||
class MembersEnumeration implements Enumeration<Principal>
|
||||
{
|
||||
private Iterator<? extends Principal> itor;
|
||||
|
||||
public MembersEnumeration (Iterator<? extends Principal> itor)
|
||||
{
|
||||
this.itor = itor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMoreElements ()
|
||||
{
|
||||
return this.itor.hasNext();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Principal nextElement ()
|
||||
{
|
||||
return this.itor.next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new MembersEnumeration (_members.iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
if (! (object instanceof JAASGroup))
|
||||
return false;
|
||||
|
||||
return ((JAASGroup)object).getName().equals(getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName()
|
||||
{
|
||||
|
||||
return _name;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
|
||||
public interface RoleCheckPolicy
|
||||
{
|
||||
/* ------------------------------------------------ */
|
||||
/** Check if a role is either a runAsRole or in a set of roles
|
||||
* @param roleName the role to check
|
||||
* @param runAsRole a pushed role (can be null)
|
||||
* @param roles a Group whose Principals are role names
|
||||
* @return <code>true</code> if <code>role</code> equals <code>runAsRole</code> or is a member of <code>roles</code>.
|
||||
*/
|
||||
public boolean checkRole (String roleName, Principal runAsRole, Group roles);
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.security.acl.Group;
|
||||
import java.util.Enumeration;
|
||||
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
/** StrictRoleCheckPolicy
|
||||
* <p>Enforces that if a runAsRole is present, then the
|
||||
* role to check must be the same as that runAsRole and
|
||||
* the set of static roles is ignored.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class StrictRoleCheckPolicy implements RoleCheckPolicy
|
||||
{
|
||||
|
||||
@Override
|
||||
public boolean checkRole (String roleName, Principal runAsRole, Group roles)
|
||||
{
|
||||
//check if this user has had any temporary role pushed onto
|
||||
//them. If so, then only check if the user has that role.
|
||||
if (runAsRole != null)
|
||||
{
|
||||
return (roleName.equals(runAsRole.getName()));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (roles == null)
|
||||
return false;
|
||||
Enumeration<? extends Principal> rolesEnum = roles.members();
|
||||
boolean found = false;
|
||||
while (rolesEnum.hasMoreElements() && !found)
|
||||
{
|
||||
Principal p = (Principal)rolesEnum.nextElement();
|
||||
found = roleName.equals(p.getName());
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the test-jndi webapp -->
|
||||
<!-- Configure the test-jaas webapp -->
|
||||
<!-- =============================================================== -->
|
||||
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
|
Loading…
Reference in New Issue