Created
March 31, 2011 10:33
-
-
Save seyan/896155 to your computer and use it in GitHub Desktop.
トークン埋め込みによるCSRF対策
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |
</head> | |
<body> | |
不正なアクセスです! | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.SecureRandom; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServlet; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import javax.servlet.http.HttpSession; | |
import sun.misc.BASE64Encoder; | |
public class CsrfGuardFirstServlet extends HttpServlet { | |
private static final long serialVersionUID = 1L; | |
private static final int BYTE_LEN = 256; | |
/** 乱数生成アルゴリズム */ | |
private static final String ALG = "SHA1PRNG"; | |
public CsrfGuardFirstServlet() { | |
super(); | |
} | |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
//文字化け対策 | |
request.setCharacterEncoding("utf-8"); | |
response.setContentType("text/html; charset=utf-8"); | |
HttpSession session = request.getSession(); | |
//ユーザIDをセッションで管理 | |
session.setAttribute("id", request.getParameter("id")); | |
//トークンをセッションで管理 | |
session.setAttribute("CSRFToken", getToken()); | |
request.getRequestDispatcher("CSRFPage1.jsp").forward(request, response); | |
} | |
/** | |
* トークン生成 | |
* @return | |
*/ | |
private String getToken(){ | |
SecureRandom random; | |
byte[] buf = new byte[BYTE_LEN]; | |
try { | |
random = SecureRandom.getInstance(ALG); | |
byte[] seed = random.generateSeed(BYTE_LEN); | |
random.setSeed(seed); | |
//乱数バイトを生成 | |
random.nextBytes(buf); | |
} catch (NoSuchAlgorithmException e) { | |
log(e.getLocalizedMessage(), e); | |
} | |
//BASE64エンコードしてトークンを生成 | |
String token = (new BASE64Encoder()).encodeBuffer(buf); | |
return token; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.IOException; | |
import javax.servlet.ServletException; | |
import javax.servlet.http.HttpServlet; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import javax.servlet.http.HttpSession; | |
public class CsrfGuardSecondServlet extends HttpServlet { | |
private static final long serialVersionUID = 1L; | |
public CsrfGuardSecondServlet() { | |
super(); | |
} | |
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { | |
//文字化け対策 | |
request.setCharacterEncoding("utf-8"); | |
response.setContentType("text/html; charset=utf-8"); | |
if(checkToken(request)){ | |
request.getRequestDispatcher("CSRFPage2.jsp").forward(request, response); | |
}else{ | |
request.getRequestDispatcher("CSRFError.html").forward(request, response); | |
} | |
} | |
/** | |
* トークンが正しいかどうか確認 | |
* @param request | |
* @return | |
*/ | |
private boolean checkToken(HttpServletRequest request){ | |
HttpSession session = request.getSession(); | |
if( session.getAttribute("CSRFToken") == null ){ | |
return false; | |
} | |
String clientToken = request.getParameter("_CSRFToken"); | |
String serverToken = session.getAttribute("CSRFToken").toString(); | |
if(clientToken != null && !"".equals(clientToken)){ | |
if(clientToken.equals(serverToken)){ | |
return true; | |
} | |
} | |
return false; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ page language="java" contentType="text/html; charset=UTF-8" | |
pageEncoding="windows-31j"%> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |
</head> | |
<body> | |
ログインしました。<br/> | |
ユーザID:${sessionScope.id } <br /> | |
<!-- 確認用 --> | |
トークン:${sessionScope.CSRFToken } <br /> | |
<form action="CsrfGuardSecondServlet" method="POST"> | |
<input type="hidden" name="_CSRFToken" value = "${sessionScope.CSRFToken}"> | |
<input type="submit" value="次のページへ"> | |
</form> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<%@ page language="java" contentType="text/html; charset=UTF-8" | |
pageEncoding="windows-31j"%> | |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | |
</head> | |
<body> | |
ユーザID:${sessionScope.id } さん!また会いましたね!<br /> | |
<!-- 確認用 --> | |
トークン:${sessionScope.CSRFToken } <br /> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment