Question

Adding @With(Secure.class) to a controller blocks all unauthenticated access. Is there a way to enabled it only for certain actions, or to except certain actions after it's enabled on a controller?

Was it helpful?

Solution

You can't do that with the secure module. As Niels said the secure module is more an example than a solution. You can build your own security system with the @Before annotation. Here is an example:

public class Admin extends Controller {

@Before(unless={"login", "authenticate", "logout", "otherMethod"})
void checkAccess() {
    // check the cookie
}

public void login() {
    render();
}

public void authenticate(String email, String password) {
    // check the params and set a value in the cookie
}

public void logout() {
    // delete cookie
}

I recommend you to read the source code of the secure module.

OTHER TIPS

I've since found my earlier @Public solution somewhat limiting since it can't address inherited actions. I've instead gone to a class-level annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AllowGuest {

    String[] value();
}

and added this code to the beginning of the Secure.checkAccess() method:

AllowGuest guest = getControllerInheritedAnnotation(AllowGuest.class);
if (guest != null) {
    for (String action : guest.value()) {
        if (action.equals(request.actionMethod))
            return;
    }
}

which can be used like this: @AllowGuest({"list","view"})

This makes it easy to allow access to local and inherited actions, and to see which actions in a controller are unsecured.

Remove @With(Secure.class) annotation to the controller and add this piece of code inside the controller.

@Before(unless={"show"})
static void checkAccess() throws Throwable {
    Secure.checkAccess();
}

where show is the action you need to make publicly available.

In order to get what I was looking for, I copied the Check annotation and created a Public annotation.

package controllers;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Public {

}

then I added these two lines to the beginning of the Secure.checkAccess:

if (getActionAnnotation(Public.class) != null)
    return;

Now actions in controllers using With(Secure.class) can be made accessible without logging in by adding a @Public annotation to them.

You can set at the @Before-Tag of the Secure Controller the value unless or only. The Secure-Module is more an example than a solution.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top