开发者

User not detected as being logged in until '/login' url is hit

I'm using the Play! Framwork with the standard Secure module. What i am seeing, is when a user logs in, and checks remember me, everything works fine. If they close the browser window, re-open and go back to the page, the user is not logged in anymore, but if they goto the default login url '/login', it automatically logs them in and redirects back to the home page with the user correctly being show as logged in.

What is going wrong that the user has to hit the login url for the site to detect they are logged in? Am i missing something in my controller to do this?

Here is the controller in question, and my custom 开发者_StackOverflow社区Security class:

public class Main extends Controller {

    @Before
    public static void checkUser() {
        String user = Security.connected();
        boolean connected = Security.isConnected();
        renderArgs.put("isConnected", connected);
        if (!connected) return;
        User u = User.findUser(user);
        String displayName = u.firstName + " " + u.lastName;
        renderArgs.put("displayName", displayName);
    }

    public static void homePage() {

        List<Testimonial> testimonials = Testimonial.findAll();
        List<News> news = News.findAll();

        Twitter twitter = new TwitterFactory().getInstance();
        List<TweetView> tweets = new ArrayList<TweetView>();
        try {
            List<Status> result = twitter.getUserTimeline("atmospherian");
            for (Status s: result) {
                String source = s.getSource();
                String content = s.getText();
                tweets.add(new TweetView(source, content));
            }

        } catch (TwitterException ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
        if (tweets.size() > 0) {
            tweets = tweets.subList(0, 3);
        }

        render(testimonials, news, tweets);
    }
}

public class Security extends Secure.Security {
    static boolean authenticate(String username, String password) {
        User user = User.find("byEmail", username).first();
        return user != null && user.password.equals(Crypto.passwordHash(password));
    }

    static boolean check(String profile) {
        if ("admin".equals(profile)) {
            return User.find("byEmail", connected()).<User>first().isAdmin;
        }

        return false;
    }
}


Now that we've established that you're not using @With(Secure.class) on this controller I've got a different answer. Secure's checkAccess method doesn't get called in this case. You could add this method to your controller:

private static void loadCookieIfPresent() {
    Http.Cookie remember = request.cookies.get("rememberme");
    if (remember != null && remember.value.indexOf("-") > 0) {
        String sign = remember.value.substring(0, remember.value.indexOf("-"));
        String username = remember.value.substring(remember.value.indexOf("-") + 1);
        if (Crypto.sign(username).equals(sign)) {
            session.put("username", username);
        }
    }
}

and call it in the beginning of your checkUser method to read the cookie without forcing a login.


I suspect this is because the login check is also triggered using a @Before annotation, so they may be executing in the wrong order:

public class Secure extends Controller {

    @Before(unless={"login", "authenticate", "logout"})
    static void checkAccess() throws Throwable {
        // Authent
        if(!session.contains("username")) {
            flash.put("url", request.method == "GET" ? request.url : "/"); // seems a good default
            login();
        }
    ...

I'm not sure if the ordering is even defined for multiple @Before methods. Quick fix would be to remove the @Before from checkUser and just call it at the beginning of your homePage method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜