Использование Cookies в приложении JSF для запоминания учетных данных для входа [duplicate]

Я знаю, что это старый вопрос, но я наткнулся на него в своем собственном поиске для сканирования по траектории и нашел еще один хороший ответ, поэтому я добавляю его здесь.

Google Guava имеет объект ClassPath , который обеспечивает «наилучшее усилие» сканирование классов (на самом деле это все предложения утилиты сканирования классов). Поскольку Guava является широко принятой, тщательно укомплектованной библиотекой утилиты, это отличный вариант для проектов, которые либо (а) уже используют Guava, либо (b) нуждаются в стабильной библиотеке, на которую они могут положиться для сканирования пути к классам.

50
задан BalusC 14 September 2015 в 13:21
поделиться

3 ответа

Java EE 8 и up

Если вы используете Java EE 8 или новее, поместите @RememberMe в пользовательский HttpAuthenticationMechanism а также RememberMeIdentityStore .

@ApplicationScoped
@AutoApplySession
@RememberMe
public class CustomAuthenticationMechanism implements HttpAuthenticationMechanism {

    @Inject
    private IdentityStore identityStore;

    @Override
    public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext context) {
        Credential credential = context.getAuthParameters().getCredential();

        if (credential != null) {
            return context.notifyContainerAboutLogin(identityStore.validate(credential));
        }
        else {
            return context.doNothing();
        }
    }
}

public class CustomIdentityStore implements RememberMeIdentityStore {

    @Inject
    private UserService userService; // This is your own EJB.

    @Inject
    private LoginTokenService loginTokenService; // This is your own EJB.

    @Override
    public CredentialValidationResult validate(RememberMeCredential credential) {
        Optional<User> user = userService.findByLoginToken(credential.getToken());
        if (user.isPresent()) {
            return new CredentialValidationResult(new CallerPrincipal(user.getEmail()));
        }
        else {
            return CredentialValidationResult.INVALID_RESULT;
        }
    }

    @Override
    public String generateLoginToken(CallerPrincipal callerPrincipal, Set<String> groups) {
        return loginTokenService.generateLoginToken(callerPrincipal.getName());
    }

    @Override
    public void removeLoginToken(String token) {
        loginTokenService.removeLoginToken(token);
    }

}

Вы можете найти пример реального мира в Java EE Kickoff Application .


Java EE 6/7

Если вы используете Java EE 6 или 7, homegrow - долгоживущий cookie для отслеживания уникального клиента и использования API-интерфейса Servlet 3.0 при условии, что он имеет программный вход HttpServletRequest#login() , когда пользователь не вошел в систему, но файл cookie присутствует.

Это самый простой для достижения, если вы создаете другую таблицу БД со значением java.util.UUID как ПК и идентификатором соответствующего пользователя как FK.

Предположим, что следующая форма входа:

<form action="login" method="post">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="checkbox" name="remember" value="true" />
    <input type="submit" />
</form>

И следующее в doPost() методе Servlet, которое отображается на /login:

String username = request.getParameter("username");
String password = hash(request.getParameter("password"));
boolean remember = "true".equals(request.getParameter("remember"));
User user = userService.find(username, password);

if (user != null) {
    request.login(user.getUsername(), user.getPassword()); // Password should already be the hashed variant.
    request.getSession().setAttribute("user", user);

    if (remember) {
        String uuid = UUID.randomUUID().toString();
        rememberMeService.save(uuid, user);
        addCookie(response, COOKIE_NAME, uuid, COOKIE_AGE);
    } else {
        rememberMeService.delete(user);
        removeCookie(response, COOKIE_NAME);
    }
}

(COOKIE_NAME должно быть уникальным именем cookie, например "remember" и COOKIE_AGE должен быть временем в секундах, например 2592000 в течение 30 дней)

Вот как метод doFilter() для Filter, который отображается на re строковые страницы могут выглядеть так:

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
User user = request.getSession().getAttribute("user");

if (user == null) {
    String uuid = getCookieValue(request, COOKIE_NAME);

    if (uuid != null) {
        user = rememberMeService.find(uuid);

        if (user != null) {
            request.login(user.getUsername(), user.getPassword());
            request.getSession().setAttribute("user", user); // Login.
            addCookie(response, COOKIE_NAME, uuid, COOKIE_AGE); // Extends age.
        } else {
            removeCookie(response, COOKIE_NAME);
        }
    }
}

if (user == null) {
    response.sendRedirect("login");
} else {
    chain.doFilter(req, res);
}

В сочетании с этими вспомогательными методами cookie (слишком плохо они отсутствуют в API сервлета):

public static String getCookieValue(HttpServletRequest request, String name) {
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if (name.equals(cookie.getName())) {
                return cookie.getValue();
            }
        }
    }
    return null;
}

public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
    Cookie cookie = new Cookie(name, value);
    cookie.setPath("/");
    cookie.setMaxAge(maxAge);
    response.addCookie(cookie);
}

public static void removeCookie(HttpServletResponse response, String name) {
    addCookie(response, name, null, 0);
}

Хотя UUID чрезвычайно сложно использовать грубую силу, вы можете предоставить пользователю возможность заблокировать опцию «запомнить» на IP-адрес пользователя (request.getRemoteAddr()) и сохранить / сравнить его в базе данных. Это делает его еще более надежным.

Также полезно заменить значение UUID, когда пользователь изменил свой пароль.


Java EE 5 или ниже

Пожалуйста, обновите.

99
ответ дан BalusC 16 August 2018 в 10:25
поделиться
  • 1
    Да, это так, и он регистрируется пользователем так же, как j_security_check. Это новое в Servlet 3.0. См. Также «Программируемый вход». в учебнике JEE6: download.oracle.com/javaee/6/tutorial/doc/gjiie.html – BalusC 24 February 2011 в 02:52
  • 2
    Дело только в том, что у enduser есть какие-либо предыдущие файлы cookie, но решил отключить «запомнить меня». позже. И нет, uuid здесь неуместно, так как он не существует в таблице. Просто удалите все записи, связанные с идентификатором пользователя. – BalusC 24 February 2011 в 18:38
  • 3
    @Marcio: файлы cookie могут быть украдены, подвергнуты воздействию или подделаны различными способами, либо случайно, либо осознанно. Вы никогда не должны хранить конфиденциальную пользовательскую информацию, такую ​​как имя пользователя и пароль в файлах cookie. UUID просто обеспечивает уникальное и неописуемое значение, которое имеет собственную бесполезную информацию. – BalusC 13 April 2012 в 19:33
  • 4
    Мне очень жаль перезапускать эту старую дискуссию, но у меня есть один вопрос @BalusC: вы сохраняете пароль в открытом тексте в объекте пользователя? (Кажется, вы должны, когда вы вызываете login (... user.getPassword ()), как это представлено в вашем упорстве? – bmurauer 19 July 2013 в 13:05
  • 5
    Если вы объедините ответы @ BalusC на множество вопросов, это станет книгой, которая должна быть на вашей полке, конечно. – Swapnil 25 August 2014 в 06:41

Вы не можете полностью войти в систему через HttpServletRequest.login (имя пользователя, пароль), так как вы не должны хранить как имя пользователя, так и пароль обычного текста в базе данных. Также вы не можете выполнить этот логин с хешем пароля, который сохраняется в базе данных. Однако вам нужно идентифицировать пользователя с маркером cookie / DB, но введи его в систему без ввода пароля с помощью пользовательского модуля входа (класс Java) на основе API-интерфейса Glassfish.

См. Следующие ссылки для получения дополнительной информации. подробности:

http://www.lucubratory.eu/custom-jaas-realm-for-glassfish-3/

Пользовательская безопасность механизм в Java EE 6/7 application

3
ответ дан Community 16 August 2018 в 10:25
поделиться

Обычно это делается следующим образом:

Когда вы регистрируете пользователя, вы также устанавливаете cookie на клиенте (и сохраняете значение cookie в базе данных), истекающее через определенное время (1-2 недель).

Когда приходит новый запрос, проверьте, существует ли определенный файл cookie, и если да, посмотрите в базу данных, чтобы узнать, соответствует ли она определенной учетной записи. Если он будет соответствовать, вы «свободно» войдете в эту учетную запись. Когда я говорю свободно, я имею в виду, что вы только позволяете этой сессии читать какую-то информацию и не писать информацию. Вам нужно будет запросить пароль, чтобы разрешить параметры записи.

Это все, что есть. Хитрость заключается в том, чтобы убедиться, что «свободный» логин не может нанести большой вред клиенту. Это несколько защитит пользователя от кого-то, кто схватит его, запомнит мне cookie и попытается войти в систему как он.

21
ответ дан Mihai Toader 16 August 2018 в 10:25
поделиться
  • 1
    +1 для «свободного» подсказки для входа. – asgs 29 April 2011 в 21:22
  • 2
    Мне тоже нравится этот логин. Вы авторизованы, но еще не авторизованы. – Bill Rosmus 14 August 2012 в 07:24
Другие вопросы по тегам:

Похожие вопросы: