• taotao用户登录springMVC拦截器的实现


    在springMVC中写拦截器,只需要两步:

    一、写 java 拦截器类,实现 interceptor 拦截器接口。

    二、在 springMVC 的xml配置文件中,配置我们创建的拦截器对象及其拦截目标 url

    首先,在前台门户项目中创建一个拦截器java类:

    package com.taotao.portal.interceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.taotao.common.utils.CookieUtils;
    import com.taotao.pojo.TbUser;
    import com.taotao.portal.service.impl.UserServiceImpl;
    
    public class LoginInterceptor implements HandlerInterceptor {
        
        /**
         * 注意,因为拦截器属于Controller,而在Controller中是不能使用Value注解来获取配置文件中设置的值的,
         * 因为 Value是spring父容器加载的属性,而Controller是springMVC子容器加载的,子容器可以访问父容器中的对象,
         * 但是不能访问父容器中的属性
         * 
         * 而我们在这里还需要用到 配置文件 中的 url值,只要用变通的方法
         * 1.首先在service的实现类 UserServiceImpl 中用@Value获取到属性,并将其设置成 public类型
         * 2.在Controller这里,不注入接口,而是直接注入 UserServiceImpl 实现类
         * 这样就可以在Controller中直接使用注入的service实现类的属性了
         */
        @Autowired
        private UserServiceImpl userService;
    
        //在handler执行之前处理
        //返回值决定handler是否执行。true:执行, false:不执行
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            //判断用户是否登录
            //从cookie中取token
            String token = CookieUtils.getCookieValue(request, "TT_TOKEN");
            //根据token换取用户信息,调用sso系统的接口
            ///这里需要写一些业务 逻辑,不要在拦截器中写,单写一个service,只在这里注入并调用
            TbUser user = userService.getUserByToken(token);
            //如果取不到用户信息
            if (user==null) {
                //跳转到登录页面,把用户请求的url作为参数传递给登录页面
                response.sendRedirect(userService.SSO_BASE_URL+userService.SSO_PAGE_LOGIN
                        +"?redirect="+request.getRequestURL());
                //返回false
                return false;
            }
            //如果取到用户信息,放行
            //把用户信息放到request中,以便后面在Controller中使用用户信息
            request.setAttribute("user", user); //request中可以直接存对象,只要到了后台都可以直接存对象
    return true; } //在 handler执行之后,返回ModelAndView之前处理 @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } //返回ModelAndView之后处理(响应用户之后,可以用来处理异常) @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }

    只要实现拦截器接口,覆盖其中的方法即可。

    在方法中,我们需要写一些业务逻辑,这里其实就是用 从 cookie 中取出的 token,到redis中查询,看是否能查到用户,若能查到,说明已经登录,拦截器不拦截,继续往下访问;若查询不到,说明当前用户登录已经过期,需要携带目标 url 跳转到登录页面(以便登录完可以继续访问之前的目标 url)。

    其中用到的 service:

    package com.taotao.portal.service.impl;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Service;
    
    import com.taotao.common.pojo.TaotaoResult;
    import com.taotao.common.utils.HttpClientUtil;
    import com.taotao.pojo.TbUser;
    import com.taotao.portal.service.UserService;
    
    @Service
    public class UserServiceImpl implements UserService {
    
    
        @Value("${SSO_BASE_URL}")
        public String SSO_BASE_URL;//#单点登录系统的url SSO_BASE_URL=http://localhost:8084
        
        @Value("${SSO_USER_TOKEN}")
        private String SSO_USER_TOKEN; //#根据token获取用户信息的url user/token/
        
        @Value("${SSO_PAGE_LOGIN}")
        public String SSO_PAGE_LOGIN; //#单点登录系统登录url /page/login/
        
        @Value("${SSO_USER_LOGOUT}")
        public String SSO_USER_LOGOUT; //#退出登录     SSO_USER_LOGOUT=/user/logout/
        
        @Override
        public TbUser getUserByToken(String token) {
            try {
                //调用sso接口,根据token获取用户信息
                String json = HttpClientUtil.doGet(SSO_BASE_URL+SSO_USER_TOKEN+token);
                TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbUser.class);
                if (taotaoResult.getStatus()==200) {
                    TbUser user = (TbUser) taotaoResult.getData();
                    return user;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            //如果没有获取到user或者出现异常,都返回null
            return null;
        }
        
    }

    写好拦截器java类后,需要在SpringMVC中配置我们自定义的拦截器:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    
        <context:component-scan base-package="com.taotao.portal.controller" />
        <mvc:annotation-driven />
        <bean
            class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/jsp/" />
            <property name="suffix" value=".jsp" />
        </bean>
        
        <!-- 资源映射 因为此工程访问的是 *.html 所以不用配置静态资源映射 静态资源映射只有当web.xml中的servlet—mapping 中的url-pattern为  / 时才需要用 -->
        <!-- <mvc:resources location="/WEB-INF/css/" mapping="/css/**"/>
        <mvc:resources location="/WEB-INF/js/" mapping="/js/**"/> -->
        
        <!-- 定义文件上传解析器 -->
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- 设定默认编码 -->
            <property name="defaultEncoding" value="UTF-8"></property>
            <!-- 设定文件上传的最大值5MB,5*1024*1024 -->
            <property name="maxUploadSize" value="5242880"></property>
        </bean>
        
        <!-- 拦截器配置 -->
        <mvc:interceptors>
            <mvc:interceptor>
                <!-- 拦截订单类请求 -->
                <mvc:mapping path="/item/**"/>
                <bean class="com.taotao.portal.interceptor.LoginInterceptor"/>
            </mvc:interceptor>
        </mvc:interceptors>
    </beans>

    其中 path属性配置我们要拦截的请求路径:

    <mvc:mapping path="/item/**"/>

    这里我们拦截所有以  /item  开头的请求。

    然后bean就是配置我们自定义的java类的全限定名:

    <bean class="com.taotao.portal.interceptor.LoginInterceptor"/>

    然后我们测试:

    在门户首页搜索 商品

    因为请求不是 item 开头的,所以拦截器不拦截,然后我们点击我们搜索到的商品,发送查看商品信息请求:

     因为这回的请求是 以 /item 开头的,所以被拦截器拦截,拦截器检查到当前 的 token 没有在redis中查到对应用户,所以判断为未登录,跳转到登录页

     http://localhost:8084/page/login/

    并且携带了原 url 作为参数 redirect=http://localhost:8082/item/153984258656220.html

    然后,在跳转到登录页请求的Controller中,又将 参数 redirect 取出,放到 model域中,存到 jsp 页面上

    sso中的 PageController 中的登录页面跳转方法:

        /**
         * 跳转到登录页面
         * @param redirect 登录成功后跳转的回调页面url
         * @param model
         * @return
         */
        @RequestMapping("/login")
        public String showLogin(String redirect,Model model) {
            model.addAttribute("redirect", redirect);
            return "login";
        }
        

    前台 login.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@ page trimDirectiveWhitespaces="true" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>
        <title>登录淘淘</title>
        <link type="text/css" rel="stylesheet" href="/css/login.css"/>
        <script type="text/javascript" src="/js/jquery-1.6.4.js"></script>
    </head>
    <body>
    <div class="w">
        <div id="logo">
            <a href="http://localhost:8082" clstag="passport|keycount|login|01">
                <img src="/images/taotao-logo.gif" alt="淘淘" width="170" height="60"/>
            </a><b></b>
           </div>
    </div>
    <form id="formlogin" method="post" onsubmit="return false;">
        <div class=" w1" id="entry">
            <div class="mc " id="bgDiv">
                <div id="entry-bg" clstag="passport|keycount|login|02" style=" 511px; height: 455px; position: absolute; left: -44px; top: -44px; background: url(/images/544a11d3Na5a3d566.png) 0px 0px no-repeat;">
                </div>
                <div class="form ">
                    <div class="item fore1">
                        <span>用户名</span>
                        <div class="item-ifo">
                            <input type="text" id="loginname" name="username" class="text"  tabindex="1" autocomplete="off"/>
                            <div class="i-name ico"></div>
                            <label id="loginname_succeed" class="blank invisible"></label>
                            <label id="loginname_error" class="hide"><b></b></label>
                        </div>
                    </div>
                    <script type="text/javascript">
                        setTimeout(function () {
                            if (!$("#loginname").val()) {
                                $("#loginname").get(0).focus();
                            }
                        }, 0);
                    </script>
                    <div id="capslock"><i></i><s></s>键盘大写锁定已打开,请注意大小写</div>
                    <div class="item fore2">
                        <span>密码</span>
                        <div class="item-ifo">
                            <input type="password" id="nloginpwd" name="password" class="text" tabindex="2" autocomplete="off"/>
                            <div class="i-pass ico"></div>
                            <label id="loginpwd_succeed" class="blank invisible"></label>
                            <label id="loginpwd_error" class="hide"></label>
                        </div>
                    </div>
                    <div class="item login-btn2013">
                        <input type="button" class="btn-img btn-entry" id="loginsubmit" value="登录" tabindex="8" clstag="passport|keycount|login|06"/>
                    </div>
                </div>
            </div>
            <div class="free-regist">
                <span><a href="/page/register" clstag="passport|keycount|login|08">免费注册&gt;&gt;</a></span>
            </div>
        </div>
    </form>
    <script type="text/javascript">
        var redirectUrl = "${redirect}";
        var LOGIN = {
                checkInput:function() {
                    if ($("#loginname").val() == "") {
                        alert("用户名不能为空");
                        $("#loginname").focus();
                        return false;
                    }
                    if ($("#nloginpwd").val() == "") {
                        alert("密码不能为空");
                        $("#nloginpwd").focus();
                        return false;
                    }
                    return true;
                },
                doLogin:function() {
                    $.post("/user/login", $("#formlogin").serialize(),function(data){
                        if (data.status == 200) {
                            alert("登录成功!");
                            if (redirectUrl == "") {//如果没有回调跳转到首页
                                location.href = "http://localhost:8082";
                            } else { //有回调,跳转到回调页面
                                location.href = redirectUrl;
                            }
                        } else {
                            alert("登录失败,原因是:" + data.msg);
                            $("#loginname").select();
                        }
                    });
                },
                login:function() {
                    if (this.checkInput()) {
                        this.doLogin();
                    }
                }
            
        };
        $(function(){
            $("#loginsubmit").click(function(){
                LOGIN.login();
            });
        });
    </script>
    </body>
    </html>

    前台填写好用户名、密码后,登录表单提交,如果登录成功,前台则会继续 跳转之前要访问的 目标 url。

  • 相关阅读:
    开发一款即时通讯App,从这几步开始
    即时通讯App怎样才能火?背后的技术原理,可以从这5个角度切入
    快速搭建一个“微视”类短视频 App
    iOS Push详述,了解一下?
    怒刷3000条短视频后,我终于发现网红300万点赞的套路
    如何精准实现OCR文字识别?
    30分钟彻底弄懂flex布局
    渲染管道
    游戏引擎架构Note2
    浮点数的内存表示方法
  • 原文地址:https://www.cnblogs.com/libin6505/p/9871853.html
Copyright © 2020-2023  润新知