Cookie
Cookie
是网络编程中使用最广泛的一项技术,主要用于辨识用户身份
客户端与网站服务端通讯过程如下:
从图可以看出服务端既要返回Cookie,也要读取客户端提交的Cookie
读Cookie
使用注解读cookie:
如果知道了cookie的值则就可以通过注解的方式读取,不再需要遍历cookie数组
为
control
类的方法增加一个@CookieValue("xxxx") String xxxx
参数即可系统会自动解析并传入同名的cookie
import org.springframework.web.bind.annotation.CookieValue;
@RequestMapping("/songlist")
//JSESSIONID为注解名
public Map index(@CookieValue("JSESSIONID") String jSessionId) {
Map returnData = new HashMap();
returnData.put("result", "this is song list");
returnData.put("author", songAuthor);
returnData.put("JSESSIONID", jSessionId);
return returnData;
}
写Cookie
为control类的方法增加一个
HttpServletResponse
参数,调用response.addCookie()
方法添加Cookie实例对象即可
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@RequestMapping("/songlist")
public Map index(HttpServletResponse response) {
Map returnData = new HashMap();
returnData.put("result", "this is song list");
returnData.put("name", songName);
Cookie cookie = new Cookie("sessionId","CookieTestInfo");
// 设置的是 cookie 的域名,就是会在哪个域名下生成 cookie 值
cookie.setDomain("youkeda.com");
// 是 cookie 的路径,一般就是写到 / ,不会写其他路径的
cookie.setPath("/");
// 设置cookie 的最大存活时间,-1 代表随浏览器的有效期,也就是浏览器关闭掉,这个 cookie 就失效了。
cookie.setMaxAge(-1);
// 设置是否只能服务器修改,浏览器端不能修改,安全有保障
cookie.setHttpOnly(false);
response.addCookie(cookie);
returnData.put("message", "add cookie successfule");
return returnData;
}
Cookie的构造函数,第一个参数是cookie名称,第二个参数是cookie值
Spring Session API
如果把用户ID,登录状态等重要信息放在cookie会带来安全隐患,所以我们采用Session
Session会把重要信息存放在服务端从而避免安全隐患
读操作
与cookie相似,从HttpServletRequest
对象中取得HttpSession
对象,使用的语句是request.getSession()
,但返回的结果不是数组而是对象,在attribute
属性中用键值对的形式存储多个数据:session.getAttribute("key")
登录信息类
登录信息实例对象要在网上传输,就必须实现序列化接口Serializable
,需要根据具体的需要设计属性:
import java.io.Serializable;
public class UserLoginInfo implements Serializable {
private String userId;
private String userName;
}
操作代码:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/songlist")
public Map index(HttpServletRequest request, HttpServletResponse response) {
Map returnData = new HashMap();
returnData.put("result", "this is song list");
// 取得 HttpSession 对象
HttpSession session = request.getSession();
// 读取登录信息
UserLoginInfo userLoginInfo = (UserLoginInfo)session.getAttribute("userLoginInfo");
if (userLoginInfo == null) {
// 未登录
returnData.put("loginInfo", "not login");
} else {
// 已登录
returnData.put("loginInfo", "already login");
}
return returnData;
}
写操作
写入数据则使用setAttribute
方法,以下代码省略了校验用户名和密码:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@RequestMapping("/loginmock")
public Map loginMock(HttpServletRequest request, HttpServletResponse response) {
Map returnData = new HashMap();
// 假设对比用户名和密码成功
// 仅演示的登录信息对象
UserLoginInfo userLoginInfo = new UserLoginInfo();
userLoginInfo.setUserId("12334445576788");
userLoginInfo.setUserName("ZhangSan");
// 取得 HttpSession 对象
HttpSession session = request.getSession();
// 写入登录信息
session.setAttribute("userLoginInfo", userLoginInfo);
returnData.put("message", "login successfule");
return returnData;
}
Spring Session配置
Spring Boot提供了编程式的配置文件,主要用于配置Bean,在类上添加@Configuration
注解,表示这是一个配置类,系统会自动扫描并处理,在方法上添加@Bean
注解,表示把此方法返回的对象实例注册成Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringHttpSessionConfig {
@Bean
public TestBean testBean() {
return new TestBean();
}
}
依赖库
<!-- spring session 支持 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
配置类
在类上额外添加一个注解@EnableSpringHttpSession
,开启session,后注册两个bean:
CookieSerializer
:读写Cookie中的SessionId信息MapSessionRepository
:Session信息在服务器上的存储仓库
import org.springframework.session.MapSessionRepository;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
import java.util.concurrent.ConcurrentHashMap;
@Configuration
@EnableSpringHttpSession
public class SpringHttpSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("JSESSIONID");
// 用正则表达式配置匹配的域名,可以兼容 localhost、127.0.0.1 等各种场景
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
serializer.setCookiePath("/");
serializer.setUseHttpOnlyCookie(false);
// 最大生命周期的单位是秒
serializer.setCookieMaxAge(24 * 60 * 60);
return serializer;
}
// 当前存在内存中
@Bean
public MapSessionRepository sessionRepository() {
return new MapSessionRepository(new ConcurrentHashMap<>());
}
}
Spring Request 拦截器
Spring提供了统一处理相同逻辑的机制:
HandlerInterceptor
(拦截器)
创建拦截器
拦截器必须实现HandlerInterceptor
接口,可以在三个点进行拦截:
- Controller方法执行之前.这是最常用的拦截点,比如是否登录的验证方法
- Controller方法执行之后,如记录日志,统计方法执行时间等
- 整个请求完成后,不常用的拦截点,比如统计整个请求的执行时间时候用
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
public class InterceptorDemo implements HandlerInterceptor {
// Controller方法执行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 只有返回true才会继续向下执行,返回false取消当前请求
return true;
}
//Controller方法执行之后
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
// 整个请求完成后(包括Thymeleaf渲染完毕)
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
实现WebMvcConfigurer
创建一个类实现WebMvcConfigurer
,并实现addInterceptors()
方法,用于管理拦截器使用addPathPatterns("/**")
表示拦截所有的URL
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebAppConfigurerDemo implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 多个拦截器组成一个拦截器链
// 仅演示,设置所有 url 都拦截
registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**");
}
}