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(),
            )

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

相关推荐
ALex_zry2 小时前
SSH主机密钥验证失败:全面解决方案与技术手册
运维·ssh
厦门辰迈智慧科技有限公司3 小时前
城市排水管网流量监测系统解决方案
运维·服务器
我没有开挂3 小时前
旧 docker 版本通过 nvkind 搭建虚拟多节点 gpu 集群的坑
运维·docker·容器
qq_339282233 小时前
centos中libc.so.6No such file的解决方式
linux·运维·centos
小鸡,啄米4 小时前
centos9安装docker 配置docker代理
运维·docker·容器
水银嘻嘻4 小时前
12 web 自动化之基于关键字+数据驱动-反射自动化框架搭建
运维·前端·自动化
小嘟嚷ovo4 小时前
h5,原生html,echarts关系网实现
前端·html·echarts
在肯德基吃麻辣烫4 小时前
Netdata在Ubuntu环境下的安装与配置:构建实时系统监控与性能分析平台
linux·运维·ubuntu
十一吖i5 小时前
Vue3项目使用ElDrawer后select方法不生效
前端
只可远观5 小时前
Flutter目录结构介绍、入口、Widget、Center组件、Text组件、MaterialApp组件、Scaffold组件
前端·flutter