JavaEE8以降
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 EEKickoffApplicationにあります。
Java EE 6/7
HttpServletRequest#login()
Java EE 6または7を使用している場合は、存続期間の長いCookieをホームグローして一意のクライアントを追跡し、ユーザーがログインしていないがCookieが存在する場合は、サーブレット3.0APIが提供するプログラムログインを使用します。
java.util.UUID
これは、値がPKで、問題のユーザーのIDがFKである別のDBテーブルを作成する場合に最も簡単に実現できます。
次のログインフォームを想定します。
<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日間である必要があります)
制限されたページにマップされるaのdoFilter()
メソッドは次のようになります。Filter
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
また、ユーザーがパスワードを変更するたびに値を置き換えることもお勧めします。
JavaEE5以下
アップグレードしてください。