AdminLoginInterceptor.java 6.8 KB
Newer Older
张骞 已提交
1 2 3
package com.template.back.server.interceptor;

import cn.hutool.core.util.ObjectUtil;
4
import com.alibaba.fastjson.JSON;
张骞 已提交
5 6 7
import com.template.back.common.pojo.system.Admin;
import com.template.back.common.utils.AdminThreadLocal;
import com.template.back.common.utils.NoAuthorization;
8
import com.template.back.common.vo.R;
张骞 已提交
9 10 11
import com.template.back.server.service.system.AdminService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
12
import org.springframework.beans.factory.annotation.Value;
张骞 已提交
13 14
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
15
import org.springframework.util.AntPathMatcher;
张骞 已提交
16 17 18 19 20 21 22 23 24 25 26 27 28 29
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

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

/**
 * @author 张骞
 * @version 1.2
 * 验证后台用户登录的拦截器,并且将用户信息写入AdminThreadLocal
 */
@Component   //注解加载到spring容器中
@Slf4j  //日志注解
public class AdminLoginInterceptor implements HandlerInterceptor {
30 31 32 33 34

    //knife4j框架的doc文档地址开关
    @Value("${doc-interceptor-state}")
    private Boolean docState;

张骞 已提交
35 36 37 38
    //注入业务层对象,用来验证用户登录信息
    @Autowired
    private AdminService adminService;

39 40 41
    //创建路径匹配器对象
    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

张骞 已提交
42 43 44 45
    //注入redis模板类,用于每次验证写入用户登录信息
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

46 47
    private static String sessionId = null;

张骞 已提交
48 49 50 51 52 53 54 55 56 57 58
    /**
     * 请求的前置处理,将User对象写入到ThreadLocal中
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
59 60 61 62 63 64 65
        //00.获取sessionId
        sessionId = request.getSession().getId();

        //01.获取本次请求的URI
        String url = request.getRequestURI();
        log.info("拦截到请求:{}", url);

张骞 已提交
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
        //将Admin对象写入到ThreadLocal中
        //校验当前的Handler
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //判断当前请求是否添加了NoAuthorization注解,如果添加了就跳过验证
        if (((HandlerMethod) handler).hasMethodAnnotation(NoAuthorization.class)) {
            return true;
        }

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            NoAuthorization noAnnotation = handlerMethod.getMethod().getAnnotation(NoAuthorization.class);
            if (noAnnotation != null) {
                // 如果该方法被标记为无需验证登录,直接返回即可
                return true;
            }
        }

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
        //2-3.对knife4j框架
        String[] docUrls = new String[]{
                "/doc.html",  //从这里开始,是swagger框架过滤使用
                "/webjars/**",
                "/swagger-resources",
                "/v2/api-docs"
        };

        //2-3-2使用私有方法进行请求匹配
        Boolean docCheck = this.check(docUrls, url);

        //2-3-3如果不需要,则直接放行
        if (docCheck) {
            log.info("拦截到knife4j请求{}", url);
            //判断配置文件的状态,如果为true,则放行,否则不放行
            if(docState){
                return true;
            }else {
                //如果配置文件为false,则始终返回false
                return false;
            }
        }


        //2-4.判断本次请求, 是否需要登录, 才可以访问
        //2-4-1定义需要过滤的数组
        String[] urls = new String[]{
                "/system/user/login",
                "/system/user/logout",
                "/backend/**",
                "/common/**",
                "/upload/**",
                "/backend/pages/login/login.html",
                "/",
                "error.jsp",
                "*.js",
                "*.css"
        };
        //2-4-2使用私有方法进行请求匹配
        Boolean check = this.check(urls, url);

        //2-4-3如果不需要,则直接放行
        if (check) {
            log.info("本次请求{}不需要进行登录拦截", url);
            return true;
        }

张骞 已提交
133 134 135 136 137 138 139 140 141 142
        //01.从session中拿到当前登录的用户数据
        Admin admin = (Admin) request.getSession().getAttribute("admin");
        //02.验证数据是否为空,如果不为空,则在数据库中查询用户信息
        if(ObjectUtil.isNotEmpty(admin)){
            //调用业务层验证的方法
            if(null != admin.getAdminId() || null != admin.getUserName() || null!= admin.getPassword()){
                Admin admin1 = this.adminService.findAdminById(admin.getAdminId(),admin.getUserName(),admin.getPassword());
                if(null != admin1){
                    //用户验证成功,写入数据
                    AdminThreadLocal.set(admin1);
143 144
                    //04-3-2重新写入session,为session延时
                    request.getSession().setAttribute("admin", admin);
张骞 已提交
145 146 147 148 149 150 151
                    log.info("过滤器层返回数据:后台用户校验成功!");
                    return true;
                }
            }
        }

        //03用户状态验证失败,返回到登录页面
152 153
//        response.sendRedirect(request.getContextPath() + "/backend/pages/login/login.html");
        response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
张骞 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
        log.error("过滤器层返回数据:用户登录验证失败!");
        return false;
    }

    /**
     * 请求结束的后置处理,将User对象从ThreadLocal中删除
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //将User对象从ThreadLocal中删除
        AdminThreadLocal.remove();
        //把登录状态信息从redis中删除
    }
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

    /**
     * 路径匹配,检查本次请求是否需要放行
     *
     * @param urls
     * @param uri
     * @return
     */
    private Boolean check(String[] urls, String uri) {
        //01.遍历要放行的请求集合
        for (String url : urls) {
            //02.调用请求匹配器的方法
            boolean match = PATH_MATCHER.match(url, uri);
            //03.如果匹配,返回true
            if (match) {
                return true;
            }
        }
        //04.如果不匹配,返回false
        return false;
    }
张骞 已提交
193 194 195
}