登录拦截

  • Post author:
  • Post category:其他


登录拦截

  • OK,比较常见的就是Spring Security安全框架,为的就是保护接口不被直接调用,只有通过登录后,才可以调用项目内的接口,这里呢,我讲一种比较常见的用法,利用session和拦截器解决这个问题

我们一步一步分析一下,

  • 1、首先我们要拦截所有的请求,这里要注意的是要对登录等接口进行放行

  • 2、要对拦截下的所有请求进行处理,判断用户是否有权限调用,才可以进行放行

  • 3、有了登录,那么对应的就要退出登录,

基本就这三块,细说一下流程

  • 1、拦截器的配置


    • web.xml

      :这没有太多的要求,重点在SpringMVC中进行配置,这里分析一个比较全面web.xml文件

    • <?xml version="1.0" encoding="UTF-8"?>
      <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://java.sun.com/xml/ns/javaee"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          id="WebApp_ID" version="2.5">
      ​
          <!--指定页面加载的初始页面 -->
          <!-- <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> -->
      ​
          <!-- 加载spring容器 -->
          <context-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>classpath:spring/applicationContext*.xml</param-value>
          </context-param>
          <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>
          
          <!-- 解决跨域问题 -->
          <!-- CORS -->
          <filter>
              <filter-name>CORS</filter-name>
              <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
              <init-param>
                  <param-name>cors.allowOrigin</param-name>
                  <param-value>*</param-value>
              </init-param>
              <init-param>
                  <param-name>cors.supportedMethods</param-name>
                  <param-value>GET, POST, HEAD, PUT, DELETE,OPTIONS</param-value>
              </init-param>
              <init-param>
                  <param-name>cors.supportedHeaders</param-name>
                  <param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified, Access-Control-Allow-Origin</param-value>
              </init-param>
              <init-param>
                  <param-name>cors.exposedHeaders</param-name>
                  <param-value>Set-Cookie</param-value>
              </init-param>
              <init-param>
                  <param-name>cors.supportsCredentials</param-name>
                  <param-value>true</param-value>
              </init-param>
          </filter>
          <filter-mapping>
              <filter-name>CORS</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
          <!-- 解决post乱码 -->
          <filter>
              <filter-name>CharacterEncodingFilter</filter-name>
              <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
              <init-param>
                  <param-name>encoding</param-name>
                  <param-value>utf-8</param-value>
              </init-param>
              <!-- <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> 
                  </init-param> -->
          </filter>
          <filter-mapping>
              <filter-name>CharacterEncodingFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
          <!-- springmvc的前端控制器 -->
          <servlet>
              <servlet-name>aiot-manager</servlet-name>
              <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
              <!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
              <init-param>
                  <param-name>contextConfigLocation</param-name>
                  <param-value>classpath:spring/springmvc.xml</param-value>
              </init-param>
              <load-on-startup>1</load-on-startup>
          </servlet>
          <servlet-mapping>
              <servlet-name>aiot-manager</servlet-name>
              <url-pattern>/</url-pattern>
          </servlet-mapping>
          <!-- 解决日志输出问题,存放 -->
          <context-param>
              <param-name>webAppRootKey</param-name>
              <param-value>aiot.root</param-value>
          </context-param>
          <context-param>
              <param-name>log4jConfigLocation</param-name>
              <param-value>/WEB-INF/classes/resource/log4j.properties</param-value>
          </context-param>
          <listener>
              <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
          </listener>
          <!--当系统出现404错误,跳转到页面nopage.html -->
          <error-page>
              <error-code>404</error-code>
              <location>/index.html</location>
          </error-page>
          <!--会话超时配置,单位分钟 -->
          <session-config>
              <session-timeout>360</session-timeout>
          </session-config>
      </web-app>
  • 对应的SpringMVC中进行配置:

    • <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:context="http://www.springframework.org/schema/context"
          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.xsd  
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      ​
          <!-- Springmvc的配置文件 ,包含网站跳转逻辑的控制,配置 -->
          <!-- <context:component-scan base-package="com.alone.controller" annotation-config="false"> 
              只扫描控制器 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> 
              </context:component-scan> -->
      ​
          <!-- 第一步:开启springioc 自动扫描注解 -->
          <context:component-scan base-package="com.xx.controller" />
      ​
          <!-- 拦截器,拦截所有的请求  这里是重点 -->
          <mvc:interceptors>
              <mvc:interceptor>
                  <mvc:mapping path="/**" />
                  <bean class="com.aiot.service.session.LoginInterceptor" />
              </mvc:interceptor>
          </mvc:interceptors>
          
          <!-- 配置视图解析器,方便页面返回 -->
          <bean
              class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/html/"></property>
              <property name="suffix" value=".html"></property>
          </bean>
      ​
          <!-- 资源映射,这里的作用就是为了方便jsp页面中前缀文件的获取,这里后期可以改一下,根据前段要求来更改位置 -->
          <mvc:resources location="/WEB-INF/css/" mapping="/css/**"></mvc:resources>
          <mvc:resources location="/WEB-INF/js/" mapping="/js/**"></mvc:resources>
      ​
      ​
          <!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
          <bean id="mappingJacksonHttpMessageConverter"
              class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
              <property name="supportedMediaTypes">
                  <list>
                      <value>text/html;charset=UTF-8</value>
                      <value>application/json;charset=UTF-8</value>
                  </list>
              </property>
          </bean>
          <!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射, 配置一个基于注解的定制的WebBindingInitializer,解决日期转换问题,方法级别的处理器映射 -->
          <bean
              class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
              <property name="cacheSeconds" value="0" />
              <property name="messageConverters">
                  <list>
                      <ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 -->
                  </list>
              </property>
              <property name="webBindingInitializer">
                  <bean class="com.aiot.util.MyWebBinding" />
              </property>
          </bean>
      ​
          <!-- 两个标准配置 -->
          <!-- 将springmvc不能处理的请求交给tomcat -->
          <mvc:default-servlet-handler />
          <!-- 能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax..映射动态请求 -->
          <mvc:annotation-driven />
  • 拦截器对应的类

    • import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      ​
      import org.springframework.web.servlet.HandlerInterceptor;
      import org.springframework.web.servlet.ModelAndView;
      ​
      import com.aiot.util.ConstantAiot;
      import com.aiot.util.LoggerUtil;
      /**
      * @ClassName: LoginInterceptor
      * @Description: 该类用于拦截类,拦截所有的请求,进行校验,判断用户是否在session中有信息, 
      * @author boway
      * @date 2018年8月1日
      *
      */
      public class LoginInterceptor implements HandlerInterceptor {
          private static final String[] URI_ACTION  = {"login"};
          
          @Override
          public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
                  throws Exception {
          }
          @Override
          public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                  throws Exception {
          }
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception {
              String url = request.getRequestURI();
              LoggerUtil.info("访问路径   " + url);
              for (String urls : URI_ACTION) {
                  if (url.contains(urls)) {
                      return true;
                  }
              }
              System.out.println(request.getSession().getAttribute(ConstantAiot.USER_CONTEXT));
              if(request.getSession().getAttribute(ConstantAiot.USER_CONTEXT)!=null) {
                  return true;
              }
              request.getRequestDispatcher("/login.html").forward(request, response);
              //这是跳转至请求
      //      arg1.sendRedirect("user/login");
              return false;
          }
       
      }
  • 这里提供一个Session的工具类,方便使用

    • package com.aiot.service.session;
      import javax.servlet.http.HttpServletRequest;
      import org.springframework.stereotype.Component;
      import com.aiot.entity.UserInfo;
      import com.aiot.util.ConstantAiot;
      /**
      * @ClassName: BaseController
      * @Description: 该类用于将用户信息存放或清除session
      * @author boway
      * @date 2018年8月1日
      *
      */
      @Component
      public class BaseSession {
          /**
          * @Title: setSessionUser
          * @Description: 将数据放入session中,并设置过期时间
          * @param @param request
          * @param @param user    参数
          * @return void    返回类型
          * @throws
          */
          public void setSessionUser(HttpServletRequest request,UserInfo user) {
              request.getSession().setMaxInactiveInterval(100 * 60);
              request.getSession().setAttribute(ConstantAiot.USER_CONTEXT, user);
          }
          public UserInfo getSessionUser(HttpServletRequest request) {
              return (UserInfo)request.getSession().getAttribute(ConstantAiot.USER_CONTEXT);
          }
          public void removeSessionUser(HttpServletRequest request) {
              request.getSession().removeAttribute(ConstantAiot.USER_CONTEXT);//清空session信息
              request.getSession().invalidate();//清除 session 中的所有信息
              //return (UserInfo)request.getSession().getAttribute(ConstantAiot.USER_CONTEXT);
          }
      } 
  • 下面就是controller类了

    • /**
      * @ClassName: UserController
      * @Description: 用户登录controller类,现用于用户登录
      * @author lenovo
      * @date 2018年7月9日
      */
      @Controller
      @RequestMapping("/user")
      public class UserLoginController {
          
          private static Logger logger = Logger.getLogger(UserLoginController.class);
          
          @Autowired
          private UserLoginService userLoginService;
          
          @Autowired
          private BaseSession baseSession;
          /**
           * @throws Exception 
          * @Title: loginUser
          * @Description: 用户登录验证对应的controller层方法
          * @param @param aiotUserT
          * @param @return    参数
          * @return String    返回类型
          * @throws
          */                       
          @RequestMapping(value="/login",method=RequestMethod.POST)
          @ResponseBody
          public Msg loginUser(HttpServletRequest request,UserInfo userInfo){
              //这里判断为空,建议使用JSR303进行校验,我这就简单示范
              if (userInfo.getUsername() == null  || userInfo.getPassword() == null) {
                  return Msg.fail().setMsg("参数为空登录失败");
              }
              logger.info("UserController.loginUser() start aiotUserT" + userInfo);
              try {
                  //这里是对密码进行加密操作,我这里使用的AES加密,建议也使用这种加密方式
                  String aesDecrypt = AESUtil.aesEncrypt(userInfo.getPassword());
                  userInfo.setPassword(aesDecrypt);
              } catch (Exception e) {
                  return Msg.fail().setMsg("登录异常");
              }
              Msg checkUser = userLoginService.checkUser(userInfo);
              if (checkUser.getCode() == 200) {
                  //这里是校验数据是否存在,如果存在就放入到session中,要注意的要将密码清空
                  UserInfo object = (UserInfo) checkUser.getExtend().get("userInfo");
                  baseSession.setSessionUser(request,object);
              }
              logger.info("UserController.loginUser() end loginMsg " + checkUser);
              return checkUser;
          }
          
          /**
          * @Title: loginUserOut
          * @Description: 退出登录
          * @param @param request
          * @param @param response
          * @param @return    参数
          * @return Msg    返回类型
          * @throws
          */
          @RequestMapping(value="/loginOut",method=RequestMethod.POST)
          @ResponseBody
          public Msg loginUserOut(HttpServletRequest request,HttpServletResponse response){
              logger.info("UserController.loginUser() start loginUserOut");
              UserInfo user=baseSession.getSessionUser(request);
              System.out.println("user    " + user);
              baseSession.setSessionUser(request, null);
              return Msg.success().setMsg("退出登录成功");
          }
      }
  • 代码到这里就OK了,



版权声明:本文为weixin_41905099原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。