rust中使用actix-session时设置Cookie失败问题

问题:浏览器端cookie没有设置成功, 后来注意到header的Set-Cookie:参数后面有带着secure的属性。

提示:

尝试通过Set-Cookie标头设置Cookie时被阻止,因为它具有"Secure"属性,但未通过安全连接发送

This attempt to set a cookie via a Set-Cookie header was blocked because it had the Secure attribute but was not recerved over a secure connection

原因:

设置了secure属性的cookie只能用https协议发送给服务器

解决

去掉secure属性,可以使用http协议发送给服务器

复制代码
setcookie(
    string $name,
    string $value = "",
    int $expires = 0,
    string $path = "",
    string $domain = "",
    bool $secure = false,
    bool $httponly = false
): bool

secure属性设置这个 Cookie 是否仅仅通过安全的 HTTPS 连接传给客户端。 设置成 true 时,只有安全连接存在时才会设置 Cookie。 如果是在服务器端处理这个需求,程序员需要仅仅在安全连接上发送此类 Cookie。

通常无法设置cookie还有其他原因比如跨域问题,显然这里不是,只是在测试环境里使用默认https链接,对于一般开发环境使用http,这里没有使用跨域请求,如果使用了,需要在后端设置,还需要在前端设置允许请求携带cookie,特别是ajax请求。举例java中设置跨域

复制代码
public class CorsInterceptor extends HandlerInterceptorAdapter {

    @Value("${service.corsOrigin}")  //跨域自定义配置application.yml自己配置
    private String corsOrigin;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String origin = request.getHeader("Origin");
        //后端响应基本配置项
        if (!StringUtils.isEmpty(origin) && corsOrigin.contains(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET");
            response.setHeader("Access-Control-Allow-Credentials", "true");
        }
        //设备默认值
        response.setContentType("application/json;charset=UTF-8");
        return true;
    }
}

setHeader设置的必要性

"Access-Control-Allow-Origin"需要指定前端指定域名,不能用*号,否则无法实现跨域

"Access-Control-Allow-Credentials" 设置成true是告知前端可以请求头携带cookie请求,否则前端将无法进行请求,另外前端每次都会发两次请求,其中首次是options请求,该请求为试探性请求可以被拦截器捕获,然后给与前端上述响应的内容,告知对它开放的一些权限及要求。

2.拦截器最后要实现WebMvcConfigurer开启拦截器配置,否则上面的代码无法生效,springMVC机制

复制代码
@Configuration
public class BaseInterceptor implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getCorsInterceptor());
    }

    @Bean
    public CorsInterceptor getCorsInterceptor() {
        return new CorsInterceptor();
    }
}

这里使用的是actix-session框架,session存在redis中默认需要安装链接才能存储cookie,否则会被禁止。

解决:要解决无法设置cookie问题回归cookie的属性上,目前已经携带secure属性,要求是https的方式才能接收,现在要做的是将该属性去除或者设置false。

解决方式:在中间件层额外设置cookie的属性设置,如果使用redis存储添加依赖

复制代码
//redis 
cargo add actix-session --features=redis-session
//本地服务器
cargo add actix-session --features=cookie-session
//redis服务器安装认证
cargo add actix-session --features=redis-session-native-tls
//其他
cargo add actix-session --features=redis-session-rustls

这里拿redis举例,

复制代码
//构建中间键插件
fn session_middleware(redis: RedisSessionStore) -> SessionMiddleware<RedisSessionStore> {
    //  RedisActorSessionStore::new("127.0.0.1:6379");
    SessionMiddleware::builder(redis, Key::from(&[0; 64]))
        .cookie_name(String::from("my-kata-cookie")) // arbitrary name
        .cookie_secure(false) // https only
        .session_lifecycle(BrowserSession::default()) // expire at end of session
        .cookie_same_site(SameSite::Lax)
        .cookie_content_security(CookieContentSecurity::Private) // encrypt
        .cookie_http_only(true) // disallow scripts from reading
        .build()
}

//在应用上加入该方法添加中间件
 .wrap(session_middleware(redis_store.clone()))

如上所示修改cookie的属性通过构建的方式来完成,很多会学习其他编程语言习惯从httpResonse中处理,在rust中没有提供基础功能,甚至那些最基础的功能也要靠导入包完成,这主要是rust还不够成熟,包的变更兼容差异很大,如上所示Cookie的secure属性设置为false,前端收到就不会报安全连接使用https才能保存cookie的弊端,当然如果你加一成nginx,可以过度性地将该属性直接去掉。

创建方式不同,如果您想自定义cookie的更多信息,请使用 builder 而不是 new

复制代码
  //使用默认
 .wrap(SessionMiddleware::new(redis_store.clone(), key.clone()))
   
//使用自定义
   .wrap(
                    SessionMiddleware::builder(storage.clone(), secret_key.clone())
                        .session_lifecycle(
                            PersistentSession::default().session_ttl(time::Duration::days(5)),
                        )
                        .build(),
                )

对于引用本地保存的就更简单,不需要设置连接redis处理,如下

复制代码
//本地服务器
cargo add actix-session --features=cookie-session

fn local_session_middleware() -> SessionMiddleware<CookieSessionStore> {
    SessionMiddleware::builder(CookieSessionStore::default(), Key::from(&[0; 64]))
        .cookie_name(String::from("my-kata-cookie")) // arbitrary name
        .cookie_secure(false) // https only
        .session_lifecycle(BrowserSession::default()) // expire at end of session
        .cookie_same_site(SameSite::Strict)
        .cookie_content_security(CookieContentSecurity::Private) // encrypt
        .cookie_http_only(true) // disallow scripts from reading
        .build()
}

使用redis存储时,注意先构建存储实例,不同的存储方式实例创建不同,这里是在外面创建传入函数,还可以直接使用构建类型,直接创建如下:

复制代码
 .wrap(
                SessionMiddleware::builder(
                    RedisActorSessionStore::new("127.0.0.1:6379"),
                    secret_key.clone(),
                )
                .build(),
            )

总结不易,希望点赞多多关注。

相关推荐
今晚吃什么呢?3 分钟前
前端面试题之CSS中的box属性
前端·css
我是大龄程序员6 分钟前
Babel工作理解
前端
程序猿(雷霆之王)20 分钟前
Linux——冯 • 诺依曼体系结构&操作系统初识
linux·运维·服务器
CopyLower20 分钟前
提升 Web 性能:使用响应式图片优化体验
前端
南通DXZ21 分钟前
Win7下安装高版本node.js 16.3.0 以及webpack插件的构建
前端·webpack·node.js
Mintopia1 小时前
深入理解 Three.js 中的 Mesh:构建 3D 世界的基石
前端·javascript·three.js
前端太佬1 小时前
暂时性死区(Temporal Dead Zone, TDZ)
前端·javascript·node.js
Mintopia1 小时前
Node.js 中 http.createServer API 详解
前端·javascript·node.js
xRainco1 小时前
Redux从简单到进阶(Redux、React-redux、Redux-toolkit)
前端
印第安老斑鸠啊1 小时前
由一次CI流水线失败引发的对各类构建工具的思考
前端