|
|
|
import org.restlet.Context; |
|
import org.restlet.Response; |
|
import org.restlet.data.Form; |
|
import org.restlet.data.Reference; |
|
import org.restlet.ext.crypto.CookieAuthenticator; |
|
|
|
import org.slf4j.Logger; |
|
import org.slf4j.LoggerFactory; |
|
|
|
|
|
/** |
|
* Implements CookieAuthenticator's challenge method. |
|
*/ |
|
public class DefaultCookieAuthenticator extends CookieAuthenticator { |
|
|
|
static final String LOGIN_FAILED_PARAM = "loginFailed"; |
|
|
|
public DefaultCookieAuthenticator(Context context, String realm, byte[] encryptSecretKey) { |
|
super(context, realm, encryptSecretKey); |
|
} |
|
|
|
public DefaultCookieAuthenticator(Context context, boolean optional, String realm, byte[] encryptSecretKey) { |
|
super(context, optional, realm, encryptSecretKey); |
|
} |
|
|
|
|
|
/** |
|
* This should probably be the default implementation of this method in |
|
* CookieAuthenticator. |
|
* |
|
* If the current resource has a redirect query value it means we're creating |
|
* a challenge after a failed login attempt, so we try again with a query |
|
* parameter that indicates that our last login attempt failed. |
|
* |
|
* Otherwise, this is a first login attempt, so we create a new reference |
|
* to the login path with a redirect to the current resource. |
|
* |
|
* For example, suppose the user tries to access a guarded resource at /foo. |
|
* Since /foo does not contain a redirect query value, the if test succeeds, |
|
* which results in a challenge redirection to /login?targetUri=/foo. |
|
* |
|
* If the login attempt fails, the authentication machinery now tries to |
|
* authenticate /login?targetUri=/foo. This time the redirect query value |
|
* is /foo, and we redirect to /login?loginFailed=true&targetUri/foo, which |
|
* allows the login form to let us know about the previous failure. |
|
* |
|
* This is somewhat brittle because other resources might use the redirect |
|
* query name in queries, too, which would confuse this logic. That's probably |
|
* a good reason not to use the default name, "targetUri", but at the moment |
|
* we *are* using it. |
|
*/ |
|
@Override public void challenge(Response response, boolean stale) { |
|
String loginFormPath = getLoginFormPath(); |
|
if (loginFormPath == null) { |
|
super.challenge(response, stale); |
|
} else { |
|
Reference ref = response.getRequest().getOriginalRef(); |
|
String redirectQueryName = getRedirectQueryName(); |
|
Form query = ref.getQueryAsForm(); |
|
String redirectQueryValue = query.getFirstValue(redirectQueryName, ""); |
|
|
|
if (redirectQueryValue.isEmpty()) { |
|
redirectQueryValue = new Reference(loginFormPath) |
|
.addQueryParameter(redirectQueryName, ref.toString()) |
|
.toString(); |
|
} else /* last login failed, try again */ { |
|
redirectQueryValue = new Reference(loginFormPath) |
|
.addQueryParameter(redirectQueryName, redirectQueryValue) |
|
.addQueryParameter(LOGIN_FAILED_PARAM, "true") |
|
.toString(); |
|
} |
|
|
|
response.redirectSeeOther(redirectQueryValue); |
|
} |
|
} |
|
|
|
|
|
public boolean lastLoginFailed(Form query) { |
|
return "true".equals(query.getFirstValue(LOGIN_FAILED_PARAM, "false")); |
|
} |
|
} |