package org.koshinuke.service;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.koshinuke.jersey.auth.AuthenticationFilterFactory;
import org.koshinuke.model.AuthModel;
import org.koshinuke.util.ServletUtil;
import com.sun.jersey.api.view.Viewable;
import com.sun.jersey.spi.resource.Singleton;
/**
* @author taichi
*/
@Singleton
@Path("/login")
@Produces(MediaType.TEXT_HTML)
public class UserService {
@GET
public Viewable login(@Context HttpServletRequest req,
@Context HttpServletResponse res) {
if (AuthenticationFilterFactory.isLoggedIn(req)) {
ServletUtil.redirect(res, "/");
return null;
}
return AuthModel.of("/login", req.getSession());
}
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Object login(@Context HttpServletRequest req,
@FormParam("u") String u, @FormParam("p") String p,
@FormParam("t") String t, @Context UriInfo info) {
try {
HttpSession session = req.getSession(false);
if (ServletUtil.verifyCsrf(session, t)) {
req.login(u, p);
if (session != null) {
session.invalidate();
}
AuthenticationFilterFactory.setUserPrincipal(
req.getSession(true), req);
// HttpServletResponse#sendRedirectを使い、リダイレクト先としてコンテキストルートを指定すると、
// このリクエストを送信する際にはまだHttpSessionが存在しない為に、
// URLのセッションIDと/が隣合う不適切なLocationヘッダが生成されてしまうので、回避措置。
// 尚、Set-Cookieヘッダーは正しく設定されるので、アプリケーションとしては適切に動作する。
// see. org.eclipse.jetty.server.Response#encodeURL
return Response
.status(HttpServletResponse.SC_MOVED_TEMPORARILY)
.location(info.getBaseUri()).build();
}
} catch (ServletException e) {
// login failed
}
return AuthModel.of("/login", req.getSession());
}
}