栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

自定义拦截器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

自定义拦截器

用于拦截请求,一般作用与单点登录系统。

创建拦截器

创建拦截器,必须实现接口HandlerInterceptor,并重写三个方法,添加业务

访问所有Controller中的任何方法,都会触发拦截器,执行拦截器的功能

package cn.tedu.interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

//自定义拦截器:在方法执行前后添加与业务无关的功能
@Component//交给spring管理bean的ioc di
public class MyInterceptor implements HandlerInterceptor{
    long start ;
    long end ;
    @Override //在方法执行前调用此处一般用于sso获取token。并验证如果存在则true,不存在重新登陆
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        start = System.currentTimeMillis();
        System.out.println("方法要被执行啦~");
        return true;//放行
    }
    @Override //在方法执行后调用
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        end = System.currentTimeMillis();
        System.out.println("方法执行完啦~");
    }
    @Override //都完成后调用
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("都干完啦~耗时: "+(end-start)+"ms");
    }
}

注册拦截器

注册拦截器,必须实现接口WebMvcConfigure,通知spring容器管理这个类

package cn.tedu.interceptor;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration//告诉spring容器,我是一个配置类
public class RegistInterceptor implements WebMvcConfigurer {

    @Autowired//自动装配
    private MyInterceptor a ;


    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(a)
                .addPathPatterns("
@Slf4j
@Controller
@RequestMapping("/sso")
public class SSOLoginController {


    
    @RequestMapping("/login")
    public String login(LoginParam loginParam, RedirectAttributes redirectAttributes,
                        HttpSession session, Model model) {

        //Demo 项目此处模拟数据库账密校验
        if (!"admin".equals(loginParam.getUsername()) || !"123456".equals(loginParam.getPassword())) {
            model.addAttribute("msg", "账户或密码错误,请重新登录!");
            model.addAttribute("redirectUrl", loginParam.getRedirectUrl());
            return "login";
        }

        //登录成功
        //创建令牌
        String ssoToken = UUID.randomUUID().toString();
        //把令牌放到全局会话中
        session.setAttribute("ssoToken", ssoToken);
        //设置session失效时间-单位秒
        session.setMaxInactiveInterval(3600);
        //将有效的令牌-放到map容器中(存在该容器中的token都是合法的,正式环境建议存库或者redis)--------------------------------------
        SSOConstantPool.TOKEN_POOL.add(ssoToken);

        //未携带重定向跳转地址-默认跳转到认证中心首页
        if (StringUtils.isEmpty(loginParam.getRedirectUrl())) {
            return "index";
        }

        // 携带令牌到客户端
        redirectAttributes.addAttribute("ssoToken", ssoToken);
        log.info("[ SSO登录 ] login success ssoToken:{} , sessionId:{}", ssoToken, session.getId());
        // 跳转到客户端
        return "redirect:" + loginParam.getRedirectUrl();
    }

    
    @ResponseBody
    @RequestMapping("/checkToken")
    public String verify(String ssoToken, String loginOutUrl, String jsessionid) {
        // 判断token是否存在map容器中,如果存在则代表合法
        boolean isVerify = SSOConstantPool.TOKEN_POOL.contains(ssoToken);
        if (!isVerify) {
            log.info("[ SSO-令牌校验 ] checkToken 令牌已失效 ssoToken:{}", ssoToken);
            return "false";
        }

        //把客户端的登出地址记录起来,后面注销的时候需要根据使用(生产环境建议存库或者redis)
        List clientInfoList =
                SSOConstantPool.CLIENT_REGISTER_POOL.computeIfAbsent(ssoToken, k -> new ArrayList<>());
        ClientRegisterModel vo = new ClientRegisterModel();
        vo.setLoginOutUrl(loginOutUrl);
        vo.setJsessionid(jsessionid);
        clientInfoList.add(vo);
        log.info("[ SSO-令牌校验 ] checkToken success ssoToken:{} , clientInfoList:{}", ssoToken, clientInfoList);
        return "true";
    }

    
    @RequestMapping("/checkLogin")
    public String checkLogin(String redirectUrl, RedirectAttributes redirectAttributes,
                             Model model, HttpServletRequest request) {
        //从认证中心-session中判断是否已经登录过(判断是否有全局会话)
        Object ssoToken = request.getSession().getAttribute("ssoToken");

        // ssoToken为空 - 没有全局回话
        if (StringUtils.isEmpty(ssoToken)) {
            log.info("[ SSO-登录校验 ] checkLogin fail 没有全局回话 ssoToken:{}", ssoToken);
            //登录成功需要跳转的地址继续传递
            model.addAttribute("redirectUrl", redirectUrl);
            //跳转到统一登录页面
            return "login";
        }

        log.info("[ SSO-登录校验 ] checkLogin success 有全局回话  ssoToken:{}", ssoToken);
        //重定向参数拼接(将会在url中拼接)
        redirectAttributes.addAttribute("ssoToken", ssoToken);
        //重定向到目标系统
        return "redirect:" + redirectUrl;
    }

    
    @RequestMapping("/logOut")
    public String logOut(HttpServletRequest request) {
        HttpSession session = request.getSession();
        log.info("[ SSO-统一退出 ] ....start.... sessionId:{}", session.getId());
        //注销全局会话, SSOSessionListener 监听器会处理后续操作
        request.getSession().invalidate();
        log.info("[ SSO-统一退出 ] ....end.... sessionId:{}", session.getId());
        return "logout";
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/841395.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号