Skip to content

Instantly share code, notes, and snippets.

@seyan
Created March 31, 2011 10:33
Show Gist options
  • Save seyan/896155 to your computer and use it in GitHub Desktop.
Save seyan/896155 to your computer and use it in GitHub Desktop.
トークン埋め込みによるCSRF対策
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
不正なアクセスです!
</body>
</html>
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;
}
}
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;
}
}
<%@ 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>
<%@ 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