此处本人的过滤代码如下:
仅仅是判断了这个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: