拦截器实现登录拦截和跨域问题

一、什么是拦截器:

什么是拦截器:在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略

为什么需要拦截器:在做身份认证或者是进行日志的记录时,我们需要通过拦截器达到我们的目的。最常用的登录拦截、或是权限校验、或是防重复提交、或是根据业务像12306去校验购票时间,总之可以去做很多的事情

如何用拦截器:在spring中用拦截器需要实现HandlerInterceptor接口或者它的实现子类:HandlerInterceptorAdapter,同时在applicationContext.xml文件中配置拦截器

二、定义实现类

定义一个Interceptor 非常简单方式有:
1、类要实现Spring 的HandlerInterceptor 接口
2、类继承实现了HandlerInterceptor 接口的类,例如 已经提供的实现了HandlerInterceptor 接口的抽象类HandlerInterceptorAdapter

三、HandlerInterceptor方法

boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception;

void postHandle(
		HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
		throws Exception;

void afterCompletion(
		HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
		throws Exception;

preHandle:在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
postHandle:在业务处理器处理请求执行完成后,生成视图之前执行。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView (这个博主就基本不怎么用了);
afterCompletion:在DispatcherServlet完全处理完请求后被调用,可用于清理资源等。返回处理(已经渲染了页面);

四、实战演练

1.配置yml

spring:
  application:
    name: web
  profiles:
    active: dev
visit:
  allowWebHost:
  1. 写一个拦截器 实现HandlerInterceptor 接口

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.net.URI;
import java.util.Arrays;
import java.util.UUID;

/**
 * @author 
 * @version V1.0
 * @Package 
 * @Description:  用于登录拦截
 * @date 
 */
@Component
@Slf4j
public class AuthorizeInterceptor implements HandlerInterceptor {

    @Value("${spring.profiles.active}")
    private String SPRING_PROFILES_ACTIVE;
    // ip白名单,如果配置了白名单,则只有白名单可以访问,其他地址非法跨域
    @Value("${visit.allowWebHost}")
    private String allowWebHostStr;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        //CSRF 跨站攻击简单Referer验证
        String referer = request.getHeader("referer");
        if (StringUtils.isNotEmpty(referer)) {
            URI refererUrl = new URI(referer);
            String[] allowWebHostList = allowWebHostStr.split(",");
            if (null != allowWebHostList && allowWebHostList.length > 1 && !Arrays.asList(allowWebHostList).contains(refererUrl.getHost())) {
                log.error("非法跨站请求URL:" + refererUrl);
                response.setCharacterEncoding("UTF-8");
                response.setContentType("text/html;charset=UTF-8");
                try (PrintWriter pw = response.getWriter()) {
                    pw.print(R.error(ResultCodeEnum.ILLEGAL_REQUEST.getMsg(), ResultCodeEnum.ILLEGAL_REQUEST.getCode()));
                    pw.flush();
                }
                return false;
            }
        }
        //安全header添加
        response.setHeader("XSS-Protection", "1; mode=block");
        response.setHeader("X-Content-Type-Options", "nosniff");
        response.setHeader("Content-Security-Policy", ""); // 不设置
        response.setHeader("x-frame-options", "ALLOW-FROM");
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
        //从cookie获取自定义sessionID,不存在则放置
        String sessinIdFromCookie = getSessionIdFromCookie(request, response);
        //从redis 中获取usersession信息
        UserSessionVo userSessionVo = JedisUtils.getBean(CacheKey.CRM_JDM_USER_SESSION_KEY + sessinIdFromCookie, UserSessionVo.class);
        // 登录session 验证
        if (userSessionVo == null) {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            try (PrintWriter pw = response.getWriter()) {
                pw.print(R.error(ResultCodeEnum.UNAUTHORIZED.getMsg(), ResultCodeEnum.UNAUTHORIZED.getCode()));
                pw.flush();
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * 获取自定义sessionId
     * @param request
     * @return
     */
    private String getSessionIdFromCookie(HttpServletRequest request, HttpServletResponse response){
        String sessionId = null;
        // 开发环境缓存注入方式登陆商家后台
        String localLoginSession = JedisUtils.getString(CacheKey.CRM_JDM_LOCAL_LOGIN_SESSION);
        if ("dev".equals(SPRING_PROFILES_ACTIVE) && !StringUtils.isEmpty(localLoginSession)) {
            return localLoginSession;
        }
        Cookie[] cookies = request.getCookies();
        if(null!=cookies){
            for(Cookie cookie : cookies){
                if(CacheKey.CRM_JDM_COOKIE_SESSION_ID.equals(cookie.getName())){
                    sessionId = cookie.getValue();
                    break;
                }
            }
        }
        if(StringUtils.isEmpty(sessionId)){
            sessionId =  UUID.randomUUID().toString();;
            Cookie cookie = new Cookie(CacheKey.CRM_JDM_COOKIE_SESSION_ID, sessionId);
            cookie.setHttpOnly(true);
            cookie.setPath("/");
            response.addCookie(cookie);
        }
        return sessionId;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值