由于开发一个表格系统时,前端使用的是Vue,后端使用的是 spring boot,在本地调试时用 localhost来访问,可以做到服务端和客户端使用cookie(HttpSession session) 通信,实现验证是否登录,但是在生产环境客户端(浏览器)在登录时无法set-cookie,导致cookie 信息没有保存在浏览器,其他接口无法做验证登录。 在没有使用https 的情况下,解决重要步骤:

报错信息如图:
在这里插入图片描述

一、 前端部分

我使用的是vue-admin-template
文件目录修改如下:

  1. 属性设置:withCredentials: true,
// 目录: vue-admin-template\src\utils\request.js
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
  withCredentials: true, // send cookies when cross-domain requests
  timeout: 50000 // request timeout
})
  1. 注释引入mock
// 目录: vue-admin-template\src\main.js
// if (process.env.NODE_ENV === 'production') {
//   const { mockXHR } = require('../mock')
//   mockXHR()
// }

3.前端使用Nginx代理的地址,与客户端访问地址、后端设置跨域地址保持一致

// 目录: vue-admin-template\.env.production
# just a flag
ENV = 'production'

# base api

VUE_APP_BASE_API = 'http://a.xxx.top/demo'

二、后端部分

  1. 跨域设置
package com.xx.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://a.xxx.top")
                .allowCredentials(true)
                .allowedMethods("*")
                .maxAge(3600);
    }

}
  1. application.yml 文件设置
server:
  port: 8088
  servlet:
    context-path: /demo
    session:
      cookie:
        domain: a.xxx.top
      timeout: 24h
  1. 登录接口
@RequestMapping(path = "/login",method = RequestMethod.POST)
    public Object login(@RequestBody LoginParams loginParams, HttpSession session) {
        try {
            if (StringUtils.isEmpty(loginParams.getMobile())) {
                return new WebResponse(ErrorCode.NEED_MOBILE);
            }
            if (StringUtils.isEmpty(loginParams.getPassword())) {
                return new WebResponse(ErrorCode.NEED_PASSWORD);
            }
            User user = userService.login(loginParams);
            // 保存用户信息时,不保存密码
            user.setPassword(null);
            session.setAttribute(Constants.USER_INFO, user);
            // System.out.println("登录 session id :" +  session.getId());
            System.out.println("登录 creator :" +  session.getAttribute(Constants.USER_INFO));
            return new WebResponse(ErrorCode.SUCCESS, user);
        } catch (ServiceException serviceException) {
            return new WebResponse(serviceException);
        }
    }

三、 Nginx部分

server {
    listen       80;
    server_name  a.xxx.top;

    charset utf-8;

    # 允许跨域请求的域,* 代表所有
    add_header 'Access-Control-Allow-Origin' *;
    # 允许带上 cookie 请求
    add_header 'Access-Control-Allow-Credentials' 'true';
    # 允许请求的方法,比如 GET/POST/PUT/DELETE
    add_header 'Access-Control-Allow-Methods' *;
    # 允许请求的 header
    add_header 'Access-Control-Allow-Headers' *;

    location / {
        add_header Access-Control-Allow-Origin *;
        root /www/wwwroot/demo/dist;
        index index.html index.htm;
    }

	location /demo {
		proxy_pass http://111.xx.xx.69:8088;

		# 禁用 proxy_cookie_path 设置

		add_header 'Access-Control-Allow-Origin' 'http://a.xxx.top';
		add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Accept-Language';
		add_header 'Access-Control-Allow-Credentials' 'true';
		add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';

		# 设置 SameSite=None; Secure; HttpOnly
        proxy_cookie_path / "/; secure; httponly; samesite=none";
	}

}

如果出现"尝试通过 Set-Cookie 标头设置 Cookie 的提作被禁上了,因为此标头具有“Secure"属性但不是通过安全连接接收的"
解决去掉Nginx 配置中proxy_cookie_path 里的 “secure; ”

	# 设置 SameSite=None; HttpOnly
    proxy_cookie_path / "/; httponly; samesite=none";

本文参考案例:
https://blog.csdn.net/heidou_2016/article/details/127705402
https://blog.csdn.net/qq_35704369/article/details/126495891

其他改进方案

方案一:在生产环境中始终优先使用 https,以确保在客户端和服务器之间传输的数据的安全性。如果要设置带有 Secure 属性的 cookie,则必须使用 https。

方案二:后续开发过程可以考虑使用基于令牌(token)的身份验证方案,例如 JSON Web Tokens (JWT)。通过在每个请求中传递令牌,你可以绕过 SameSite Cookie 的限制。前端将令牌存储在本地,并在每个请求中将其发送到后端。后端验证令牌以进行身份验证。如果有问题欢迎留言讨论。

Logo

前往低代码交流专区

更多推荐