用户会话session

session对象主要存在服务器端,可以用于保存服务器的临时数据的对象,所保存的数据可以在整个项目中都可以通过访问来获取,把session的数据看做一个共享的数据。首次登陆的时候所获取的用户的数据,转移到session对象即可。session.getAttribute("key")可以将获取session中的数据这种行为进行封装,封装在BaseController类中。

1.封装session对象中数据的获取(封装在父类中)、数据的设置(当用户登录成功后进行数据的设置,设置到全局的session对象)。

2.在父类中封装两个数据:获取uid和获取username对应的两个方法。用户头像暂时不考虑,将来封装在cookie中来使用。

/**
     * 获取session对象中的uid
     * @param session session对象
     * @return  当前登录的用户uid的值
     */
    protected final Integer getUidFromSession(HttpSession session){
        return Integer.valueOf(session.getAttribute("uid")
                    .toString());
    }

    /**
     * 获取当前登录用户的username
     * @param session session对象
     * @return  当前登录用户的用户名称
     * 在实现类中重写父类中的toString(),不是句柄信息的输出
     */
    protected final String getUsernameFromSession(HttpSession session){
       return session.getAttribute("username").toString();
    }

3.在登陆的方法中将数据封装在session对象中。 服务器本身自动创建有session对象,已经是一个全局的session对象。SpringBoot直接使用session对象,直接将httpSession类型的对象作为请求处理方法的参数,会自动将全局的session对象注入到请求处理方法的session形参上。

@RequestMapping("login")
    public JsonResult<User> login(String username,
                                  String password,
                                  HttpSession session ){
        User data = userService.login(username, password);
        //向session对象中完成数据的绑定
        session.setAttribute("uid",data.getUid());
        session.setAttribute("username",data.getUsername());
        //获取session中绑定的数据
        System.out.println(getUidFromSession(session));
        System.out.println(getUsernameFromSession(session));
        return new JsonResult<User>(OK,data);

    }

拦截器

 拦截器:首先将所有的请求统一拦截到拦截器中,可以在拦截器中来定义过滤的规则,如果不满足系统设置的过滤规则,统一的处理是重新去打开login.html页面(重定向和转发),推荐使用重定向。

在SpringBoot项目中拦截器的定义和使用。SpringBoot是依靠SpringMVC来完成的。SpringMVC提供了一个HandlerInterceptor接口,用于表示定义一个拦截器。首先自定义一个类,再让这个类实现这个接口。

1.首先自定义一个类,让这个类实现HandlerInterceptor接口。

package com.cy.store.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;

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

/**定义一个拦截器**/
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 检测全局session对象中是否有uid数据,有则放行,没有则重定向到登陆界面
     * @param request 请求对象
     * @param response 响应对象
     * @param handler   处理器(url+Controller:映射)
     * @return 如果返回值为true放行当前的请求,如果为false,则表示拦截当前的请求
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {
        // HttpServletRequest对象来获取session对象
        Object obj = request.getSession().getAttribute("uid");
        if(obj==null){
            //说明用户没有登陆过系统,重定向到login.html界面
            response.sendRedirect("/web/login.html");
            //结束后续的调用
            return false;
        }
        //请求放行
        return true;
    }
}

2.注册过滤器:添加白名单(哪些资源可以在不登陆的i情况下访问)、添加黑名单(用户登陆的状态下才能访问的资源)

package com.cy.store.config;

import com.cy.store.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

/** 处理器拦截器的注册**/
@Configuration // 加载当前的拦截器并进行注册
public class LoginInterceptorConfigure implements WebMvcConfigurer {

    /** 配置拦截器**/
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //创建自定义的拦截器对象
        HandlerInterceptor interceptor=new LoginInterceptor();
        //配置白名单:存放在一个List集合中
        List<String> patterns=new ArrayList<>();
        patterns.add("/bootstrap3/**");
        patterns.add("/css/**");
        patterns.add("/images/**");
        patterns.add("/js/**");
        patterns.add("/web/register.html");
        patterns.add("/web/login.html");
        patterns.add("/web/index.html");
        patterns.add("/web/product.html");
        patterns.add("/users/reg");
        patterns.add("/users/login");
        //完成拦截器的注册
        registry.addInterceptor(interceptor).
                addPathPatterns("/**")
                .excludePathPatterns(patterns); //表示拦截的url是什么

    }
}

3.注册拦截器的技术:借助WebMvcConfigure接口,可以将用户定义的拦截器进行注册,才可以保证拦截器能够生效和使用。定义一个类,然后让这个类实现WebMvcConfigure接口。配置信息,建议放在项目的config包结构下。

//将自定义的拦截器进行注册
/** 处理器拦截器的注册**/
public class LoginInterceptorConfigure implements WebMvcConfigurer {
    
}

4.提示重定向次数过多,login.html页面无法打开。将浏览器cookie清楚,浏览器初始化

源码解析:

public interface HandlerInterceptor {
//在调用所有处理请求的方法之前被自动调用执行的方法
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
// 在ModelAndViex对象返回之后被调用的方法
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
// 在整个请求所有关联的资源被执行完毕最后执行的方法
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}