• Servlet - 使用 changeSessionId() 防止会话固定攻击


    会话固定攻击,黑客获取/设置(通过任何方式)另一个人的会话ID。然后,黑客可以冒充他人并获取敏感信息。

    Java Servlet 3.1 引入了以下 HttpServletRequest 方法:

    String changeSessionId()
    

    此方法将当前会话 id 更改为新的,从而提供针对会话固定攻击的保护。

    Servlet 3.1 还引入了HttpSessionIdListener用于接收 HttpSession id 更改通知。

    对于 3.1 之前的版本,我们可以使用以下步骤:

    1. HttpSession session = .....
    2. .....
    3. session.invalidate();
    4. session=request.getSession(true);
    5. //now set data from old session here

    例子

    在以下示例中,我们将学习如何使用 Servlet 3.1 API 对抗会话固定。

    登录 servlet

    1. @WebServlet(name = "userLoginServlet", urlPatterns = {"/login"})
    2. public class LogInServlet extends HttpServlet {
    3. @Override
    4. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    5. throws ServletException, IOException {
    6. HttpSession session = req.getSession();
    7. String userKey = "loggedInUser";
    8. User user = (User) session.getAttribute(userKey);
    9. if (user == null) {
    10. user = loadUserForRequest(req);
    11. session.setAttribute(userKey, user);
    12. }
    13. prepareLogginInfoHtml(user, resp);
    14. req.changeSessionId();
    15. }
    16. private void prepareLogginInfoHtml(User user, HttpServletResponse resp)
    17. throws IOException {
    18. resp.setContentType("text/html");
    19. PrintWriter w = resp.getWriter();
    20. w.write("User logged in " + user.getName());
    21. w.write("
      Show Balance");
    22. }
    23. private User loadUserForRequest(HttpServletRequest req) {
    24. //returning a dummy user
    25. return new User("1", "Mike", "12312",
    26. BigDecimal.valueOf(200000));
    27. }
    28. }
    1. public class User {
    2. private String id;
    3. private String name;
    4. private String accountNumber;
    5. BigDecimal currentBalance;
    6. .............
    7. }

    用于登录后处理的另一个 servlet

    1. @WebServlet(name = "userBalanceServlet", urlPatterns = {"/balance"})
    2. public class BalanceServlet extends HttpServlet {
    3. @Override
    4. protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    5. throws ServletException, IOException {
    6. HttpSession session = req.getSession();
    7. User user = (User) session.getAttribute("loggedInUser");
    8. if (user == null) {
    9. RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/login");
    10. dispatcher.forward(req, resp);
    11. } else {
    12. prepareBalanceInfoHtml(user, resp);
    13. req.changeSessionId();
    14. }
    15. }
    16. private void prepareBalanceInfoHtml(User user, HttpServletResponse resp) throws IOException {
    17. resp.setContentType("text/html");
    18. PrintWriter w = resp.getWriter();
    19. w.write("User logged in " + user.getName());
    20. w.write("
      Balance: " + user.getCurrentBalance());
    21. }
    22. }

    实现 AppSessionIdListener

    1. @WebListener
    2. public class AppSessionIdListener implements HttpSessionIdListener {
    3. @Override
    4. public void sessionIdChanged(HttpSessionEvent event, String oldSessionId) {
    5. System.out.println("oldSessionId: " + oldSessionId);
    6. System.out.println("newSessionId: " + event.getSession().getId());
    7. }
    8. }

    要尝试示例,请运行嵌入式 Jetty(在以下示例项目的 pom.xml 中配置):

    mvn jetty:run
    

    在本教程中,我们使用 Jetty 插件而不是 tomcat7-maven-plugin,因为 tomcat 插件不支持 Servlet 3.1(它支持最高 3.0 的版本)。

    输出

    点击“显示余额”链接:

    服务器输出

    正如我们的 HttpSessionIdListener 打印的那样:

    1. .....
    2. oldSessionId: node0md9ox8wtj0e91lr5kpuzw7dql0
    3. newSessionId: node01jl2v0v5bvfwgxvhr7ao2f52z1
    4. ....
    5. oldSessionId: node0nyhkl2ej1ret1716bwjwyl9a92
    6. newSessionId: node0mqnz9mrwfg8a1it5hxc7rdg3v3
    7. ....

    Chrome 检查 - 网络选项卡

     

    示例项目

    使用的依赖项和技术:

    • javax.servlet-api 3.1.0 Java Servlet API
    • jetty-maven-plugin 9.4.1.v20170120:Jetty maven 插件。
    • JDK 1.8
    • Maven 3.3.9
  • 相关阅读:
    经典BN很NB,精读论文《Batch Normalization》
    微信小程序rich-text 文本首行缩进和图片居中和富文本rich-text 解析多个空格不成功 &nbsp
    Web 操作技巧有哪些
    用C#开发Excel插件的强大开源工具
    隔离放大器
    阿里妈妈API 获取商品详情 全电商平台数据接口
    如何改善交通管制带来的交通拥堵?
    解释 RESTful API,以及如何使用它构建 web 应用程序
    【车间调度】基于模拟退火优化算法的的并行车间机器优化调度(Matlab代码实现)
    嵌入式软件调试(Debug)方法
  • 原文地址:https://blog.csdn.net/allway2/article/details/126679312