JBoss + JAAS. Как реализовать remember me?

0
09 июн 2015 06:37
Всем здравствуйте!

Подскажите: нужно в приложении реализовать функцию автологина. Есть ли стандартные средства для этого?

Приложение на Java EE, как веб-слой используется REST-костыль из Struts. Авторизация сделана через JAAS, настраивается в JBOSS. Пока сделал так: таблица с токенами, указывающего на пользователя. При успешном логине создаю токен в базе и отправляю пользователю cookie-у. При каждой проверке пользователя при отсутствующей сессии, смотрю наличие соотв. куки, проверяю валидность токена... только JBoss то должен сам авторизовывать и выдавать права. А для этого надо ему в функцию передавать логин и пароль стандартными средствами. Но от пароля только sha256. Можно в куку шифровать пароль при первом логине, но будет ли это безопасно?

Заранее спасибо!

Ответов: 1

0
08 июл 2015 08:20
Может кому-то надо будет, закину свое решение:

В Rest-контроллере при правильной авторизации создается токен, записывается в базу, в request добавляется cookie "remme" c токеном. Не забудьте установить для куки path="/", иначе она только для логина будет отдаваться.
Ну и свой модуль закидывается в JBoss, наследовал DatabaseServerLoginModule:

package com.***.security;

import org.jboss.security.auth.spi.DatabaseServerLoginModule;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.security.Principal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

public class ***LoginModule extends DatabaseServerLoginModule {

    protected String userRemmeTokenQuery = "select c.login from PERSISTENT_TOKEN pt, Credential c where pt.credential_id = c.credential_id and pt.token=?";
    protected String userRemmeCookieName = "remme";

    private Principal identity;

    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
        Object tmp = options.get("remmeTokenQuery");
        if (tmp != null) {
            this.userRemmeTokenQuery = tmp.toString();
        }

        tmp = options.get("userRemmeCookieName");
        if (tmp != null) {
            this.userRemmeCookieName = tmp.toString();
        }

        super.initialize(subject, callbackHandler, sharedState, options);
    }

    @Override
    public boolean login() throws LoginException {

        boolean log1 = false;

        try {
            log1 = super.login();
        } catch (LoginException e) {
            this.log.debug("Can't login via standart method");
            //e.printStackTrace();
        }

        if (log1) {
            return true;
        } else {
            String login = null;
            try {
                login = parseLoginFromCookie();
            } catch (PolicyContextException | NamingException e) {
                this.log.debug("Can't get user info via cookie");
                //e.printStackTrace();
            }

            if (login != null) {
                try {
                    identity = createIdentity(login);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                char[] credential = "".toCharArray();

                if (getUseFirstPass() == true) {    // Add the principal and password to the shared state map
                    sharedState.put("javax.security.auth.login.name", identity);
                    sharedState.put("javax.security.auth.login.password", credential);
                }
                super.loginOk = true;
                return true;

            }
        }
        return false;
    }

    private String parseLoginFromCookie() throws PolicyContextException, NamingException {

        String login = null;

        HttpServletRequest request = (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest");

        Cookie cookie = null;
        for (Cookie cookie1 : request.getCookies()) {
            if (userRemmeCookieName.equals(cookie1.getName())) {
                cookie = cookie1;
            }
        }

        if (cookie != null) {
            this.log.debug("cookie = " + cookie.getName() + " " + cookie.getValue());

            InitialContext ex = new InitialContext();
            DataSource le1 = (DataSource) ex.lookup(this.dsJndiName);


            this.log.debug("Excuting query: " + this.userRemmeTokenQuery + ", with token: " + cookie.getValue());

            try (Connection conn = le1.getConnection();
                 PreparedStatement ps = conn.prepareStatement(this.userRemmeTokenQuery)) {

                ps.setString(1, cookie.getValue());

                try (ResultSet rs = ps.executeQuery()) {

                    if (!rs.next()) {
                        this.log.debug("Query returned no matches from db");


                    } else {
                        login = rs.getString(1);
                        this.log.debug("Login for user: " + login);
                    }
                }
            } catch (SQLException e1) {
                this.log.error("SQL Exception on request token" + e1.toString());
            }
        }

        return login;
    }

    public static void main(String[] args) {
        System.out.println("Security module for ***");
    }
}
Модераторы:
Сейчас эту тему просматривают: Нет