Web笔记-session盗用安全问题(Spring Boot获取所有session及提高安全性)

此处本人的过滤代码如下:

仅仅是判断了这个session有没有被记录,有没有attribute!

某些IT论坛,就是这样的,通过session,就可以进行批量帐号操作,发取http协议。

这里演示如下,但我登录了一个号后:

我把这个sessionid放到其他机器上

也是直接被登录的(很多论坛就是这样)

这样就存在很大的安全问题。在此提供一个策略。

这里用Spring Boot框架实现。但有session时,记录并且绑定ip。过滤器那,判断这个session绑定的IP地址对不对。

对应的流程图如下:

首先有一点,获取web的所有session。

这里可以通过这种方式获取:

package com.it1995.demo.config;

import com.it1995.demo.tool.SessionUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

@Configuration
public class HttpSessionConfig {

    //这里存个备份,可以去掉的
    private static final Map<String, HttpSession> session = new HashMap<>();

    @Bean
    public HttpSessionListener httpSessionListener(){

        return new HttpSessionListener() {

            @Override
            public void sessionCreated(HttpSessionEvent se) {

                System.out.println("sessionCreated");
                session.put(se.getSession().getId(), se.getSession());
                //SessionUtil.addIDAndIP(se.getSession().getId(), "");  //这里可以不要,也可以保留
            }

            @Override
            public void sessionDestroyed(HttpSessionEvent se) {

                System.out.println("sessionDestroyed");
                session.remove(se.getSession().getId());
                SessionUtil.removeIDAndIP(se.getSession().getId());
            }
        };
    }
}

此处用一个工具类:

package com.it1995.demo.tool;


import java.util.HashMap;
import java.util.Map;

public class SessionUtil {


    static Map<String, String> sessionID_IPMap = new HashMap<>();


    public synchronized static void addIDAndIP(String sessionID, String ip){

        sessionID_IPMap.put(sessionID, ip);
        return;
    }

    public synchronized static void removeIDAndIP(String sessionID){

        sessionID_IPMap.remove(sessionID);
    }

    public synchronized static boolean isSessionAndIPRight(String sessionID, String ip){

        //这里不判断session了,直接对比里面的值,因为有重复
        //boolean haveSession = sessionID_IPMap.containsKey(sessionID);
        //if(!haveSession)
        //    return false;

        String value = sessionID_IPMap.get(sessionID);
        if(value.equals(ip))
            return true;

        return false;
    }

    //测试打印所有
    public static void printAll(){

        System.out.println(sessionID_IPMap);
    }
}

增加如下的过滤:

BackOperationInterceptor.java

package com.it1995.demo.interceptor;

import com.it1995.demo.tool.IpUtil;
import com.it1995.demo.tool.SessionUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BackOperationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.out.println("BackOperationInterceptor preHandle");
        String sessionID = request.getSession().getId();
        String ip = IpUtil.getIpAddr(request);
        if(SessionUtil.isSessionAndIPRight(sessionID, ip)){

            return true;
        }

        System.out.println("有人盗用session,已经被拦截");
        response.sendRedirect("/");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("BackOperationInterceptor");
    }
}

LoginInterceptor.java

package com.it1995.demo.interceptor;

import com.it1995.demo.tool.IpUtil;
import com.it1995.demo.tool.SessionUtil;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {


        System.out.println("LoginInterceptor preHandle");
        //System.out.println("SESSION_ID:" + request.getSession().getId() + "  ;" + "LoginUser:" + request.getSession().getAttribute("userName"));

        Object user = (String) request.getSession().getAttribute("userName");
        if(user == null) {

            response.sendRedirect("/");
            return false;
        }

        return true;
    }


    //调用前提:preHandle返回true
    //调用时间:Controller方法处理完之后
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

        System.out.println("LoginInterceptor postHandle");

//        SessionUtil.printAll();
    }
}

在login的请求中记录session

package com.it1995.demo.controller;

import com.it1995.demo.tool.IpUtil;
import com.it1995.demo.tool.SessionUtil;
import com.it1995.demo.tool.ValidCheck;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class FHController {

    @GetMapping("/login")
    public String getLoginPage(){

        return "login";
    }

    @PostMapping("/login")
    public String userLogin(@RequestParam("username") String username,
                            @RequestParam("password") String password,
                            @RequestParam("Ticket") String ticket,
                            @RequestParam("RandStr") String randStr,
                            HttpServletRequest request, HttpSession session){

        //System.out.println(username + "  " + password + "  " + ticket + "  " + randStr + "  " + IpUtil.getIpAddr(request));

        Integer evilLevel = ValidCheck.verifyTicket(ticket, randStr, IpUtil.getIpAddr(request));
        System.out.println("The verifyResult is : " + evilLevel);

        if(evilLevel <= 30){

            session.setAttribute("userName", username);
            //验证成功,下面对比数据库

            //记录session
            SessionUtil.addIDAndIP(request.getSession().getId(), IpUtil.getIpAddr(request));
            return "redirect:/controller/home";
        }
        else{


        }

        return "login";

    }
}

程序运行截图如下:

当有人盗用session:

发布了1269 篇原创文章 · 获赞 1970 · 访问量 179万+

猜你喜欢

转载自blog.csdn.net/qq78442761/article/details/104327542
今日推荐