在 svelkit 中使用 JWT 进行身份验证 API

Authentication API with JWT in svelkit

我无法使用 svelte 对我的 API 端点进行身份验证。出于安全原因,我正在尝试使用 HTTPonly cookie 通过 JWT 对我的端点进行身份验证,但是它不起作用。错误:“未提供身份验证凭据。”我看不到cookie是登录后的存储。有人可以帮忙吗?

我获取登录端点的代码

<script>
    import { goto } from '$app/navigation';

    let username = '';
    let password = '';

    const submit = async () => {
        await fetch('https://myAPI/auth/jwt/create', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            credentials: 'include',
            body: JSON.stringify({
                username,
                password
            })
        });
     goto('/auth/me');
    };
</script>

我必须说用户注册工作正常

<script>
    import { goto } from '$app/navigation';

    let username = '';
    let password = '';
    let email = '';
    let first_name = '';
    let last_name = '';

    const submitForm = async () => {
        await fetch('https://myAPi/auth/users/', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                username,
                password,
                email,
                first_name,
                last_name
            })
        });

        goto('/');
    };
</script>

我相信我现在有足够的要素来提供更准确的答案。

您的 API returns 成功登录后的 JWT 访问令牌,但 未设置任何包含该令牌的 cookie。事实上,您的 API 根本不依赖于 cookies 因为受保护的路由不需要包含 JWT 令牌的 cookie,而是包含的授权 header令牌。

这就是为什么我如此坚持要您提供 back-end 的详细实施。

在您遵循并在评论中链接的教程中,作者明确声明他打算使用 cookie 进行身份验证。此选择反映在 front-end 上(通过使用 fetch 中的 credentials: include 选项),但 也反映在 back-end 上 ,如示例所示,in the Laravel implementation of his API (line 35), or in its Node implementation(第 40-43 行)。在这两种情况下,您都可以看到 'jwt' cookie 是如何由 back-end.

显式设置和返回的

当向受保护路由发出请求时,作者还明确使用 cookie 来回读和验证令牌(例如,请参见上面 Node 示例中的第 52-54 行)。

你的API,但是,正如我上面所说的,不依赖于相同的机制,而是期望设置'Authorization'请求header。

所以这里有 2 个选项。更简单的选择是调整您的 client-side 代码以使用您的 API 提供的 Auth 机制。这意味着将您的令牌存储在例如 sessionStorage 中,并在向受保护端点发出请求时正确设置授权 header:

// login.svelte
<script>
    import { goto } from '$app/navigation';

    let username = '';
    let password = '';

    const submit = async () => {
        const result = await fetch('https://myAPI/auth/jwt/create', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                username,
                password
            })
        });
        const data = await result.json();
        const { refresh, access } = data;
        sessionStorage.setItem('token', access);
        goto('/auth/me');
    };
</script>

// auth/me.svelte
<script>
    import { onMount } from 'svelte';
    
    onMount(async () => {
        // read token from sessionStorage
        const token = sessionStorage.getItem('token');
        const result = await fetch('https://myAPI/auth/users/me', {
            method: 'GET',
            headers: { 
                'Content-Type': 'application/json',
                'Authorization': `JWT ${token}`
            }
        });
        const data = await result.json();
        console.log(data);
    });
</script>

另一种选择是将 API 中的 Auth 机制从基于 'Authorization' header 的机制修改为基于 cookie 的机制,如果这确实是您想要的,但是这会影响依赖您的 API 的其他现有服务,如果有的话。