Blitz.js에서 주의해야 할 것들(취약성 대책)
<!DOCTYPE html>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ログインフォーム</title>
<form method="post">
<input name="name" />
<input name="password" type="password" />
<button type="submit">login</button>
</form>
<script>
document.querySelector('form')?.addEventListener('submit', e => {
e.preventDefault()
const name = document.querySelector('form [name="name"]')?.value
const password = document.querySelector('form [name="password"]')?.value
fetch('/api/query', { method: 'post', body: 'SELECT * FROM users' })
.then(r => r.json())
.then(rows => {
if (rows.find(u => u.name === name && u.password === password)) {
location.href = '/admin-page'
} else {
alert('失敗しました')
}
})
})
</script>
큰일났다.그럼 위와 같은 야바타를 알게 된 후 블리츠는js로 쓴 기초 위에서
이런 코드를 쓰지 않기 위해 주의해야 할 점을 적어라.
queries와mutation
자세한 내용은 공식 설명 및 여기 기사. 참조
api,queries,mutations명칭 디렉터리의 파일은 서버 측용 코드로 처리됩니다.데이터베이스에 저장된 데이터를 조립하고 데이터베이스에서 꺼내기 위해서는 이곳에서 하는 것이 가장 좋다.
캐릭터 확인과post 사용자의 id를 사용하는create를 주의하십시오.
실행
blitz generate all articles title:String content:String belongsTo:User 후다음 코드를 생성합니다.[2] [3]
app/articles/mutations/createArticle.ts
import { Ctx } from "blitz"
import db, { ArticleCreateArgs } from "db"
type CreateArticleInput = Pick<ArticleCreateArgs, "data">
export default async function createArticle({ data }: CreateArticleInput, ctx: Ctx) {
ctx.session.authorize()
const article = await db.article.create({ data })
return article
}
app/articles/pages/articles/new.tsximport React from "react"
import Layout from "app/layouts/Layout"
import { Link, useRouter, useMutation, BlitzPage } from "blitz"
import createArticle from "app/articles/mutations/createArticle"
import ArticleForm from "app/articles/components/ArticleForm"
const NewArticlePage: BlitzPage = () => {
const router = useRouter()
const [createArticleMutation] = useMutation(createArticle)
return (
<div>
<h1>Create New Article</h1>
<ArticleForm
initialValues={{}}
onSubmit={async () => {
try {
const article = await createArticleMutation({ data: { name: "MyName" } })
alert("Success!" + JSON.stringify(article))
router.push("/articles/[articleId]", `/articles/${article.id}`)
} catch (error) {
alert("Error creating article " + JSON.stringify(error, null, 2))
}
}}
/>
<p>
<Link href="/articles">
<a>Articles</a>
</Link>
</p>
</div>
)
}
NewArticlePage.getLayout = (page) => <Layout title={"Create New Article"}>{page}</Layout>
export default NewArticlePage
pages/articles/new.tsx에서 오류가 발생했습니다.예를 들어 아래처럼 수정하면 오류가 사라지고 문제 없이 돌아가는 것처럼 보이는데...
app/articles/pages/articles/new.tsx로 변경
- import { Link, useRouter, useMutation, BlitzPage } from "blitz"
+ import { Link, useRouter, useMutation, useSession, BlitzPage } from "blitz"
// 略
+ const session = useSession()
// 略
- const article = await createArticleMutation({ data: { name: "MyName" } })
+ const article = await createArticleMutation({ data: {
+ title: "MyName",
+ content: "",
+ user: {
+ connect: { id: session.userId },
+ }
+ } })
이 실현에서 악성 사용자는 글과 관련된 작가를 자유롭게 설정할 수 있다.[4] 대책
auth 참조 목록이 정확하게 실시되었다.우선 제작
validations.ts.iPod에 대해서는 공식.를 참조하십시오.[5]
app/articles/validations.ts
import * as z from "zod"
export const CreateInput = z.object({
title: z.string(),
content: z.string(),
})
export type CreateInputType = z.infer<typeof CreateInput>
export const UpdateInput = z.object({
id: z.number(),
title: z.string(),
content: z.string(),
})
export type UpdateInputType = z.infer<typeof UpdateInput>
다음 편집createArticle.ts.입력을 제대로 검증하지 않으면 자동으로 생성할 내용을 수동으로 입력할 수 있습니다.
한 번parse에서 되돌아오는 값에서 각 속성을 추출하고 싶습니다. (zod만 사용하면) 그냥create 등에 맡겨도 괜찮습니다.
app/articles/mutations/createArticle.ts로 변경
import { Ctx } from "blitz"
+ import db from "db"
- import db, { ArticleCreateArgs } from "db"
+ import { CreateInput, CreateInputType } from "../validations"
- type CreateArticleInput = Pick<ArticleCreateArgs, "data">
+ type CreateArticleInput = { data: CreateInputType }
export default async function createArticle({ data }: CreateArticleInput, ctx: Ctx) {
ctx.session.authorize()
+ const { title, content } = CreateInput.parse(data)
+
- const article = await db.article.create({ data })
+ const article = await db.article.create({
+ data: {
+ title,
+ content,
+ user: {
+ connect: { id: ctx.session.userId },
+ },
+ },
+ })
return article
}
최종 수정new.tsx.app/articles/pages/articles/new.tsx로 변경
- const article = await createArticleMutation({ data: { name: "MyName" } })
+ const article = await createArticleMutation({ data: { title: "MyName", content: "" } })
create와 delete도 수정됩니다.필요하다면 getarticle 등도 수정해야 한다.(비공개 문장 등을 실현하려면)
app/articles/mutations/updateArticle.ts
import { Ctx, AuthorizationError } from "blitz"
import db from "db"
import { UpdateInput, UpdateInputType } from "../validations"
type UpdateArticleInput = UpdateInputType
export default async function updateArticle(input: UpdateArticleInput, ctx: Ctx) {
ctx.session.authorize()
const { id, title, content } = UpdateInput.parse(input)
const where = { id, userId: ctx.session.userId }
const data = { title, content }
const { count } = await db.article.updateMany({ where, data })
if (!count) throw new AuthorizationError()
const article = await db.article.findOne({ where })
return article
}
pages
위와 반대로 페이지의 정보가 공개됐다고 볼 수 있다.
극단적인 예이지만 예를 들면 관리자 전용 페이지로서 아래의 형식이 있어도 발견될 수 있다.
app/users/pages/[userId].tsx
<div>
<label htmlFor={id}>このユーザがガチャを引いたときの SSR 排出率を下げる</label>
<input type="checkbox" checked={checked} id={id} onChange={onChange} />
</div>
후기
취약성 대책 이외에 Prism의 experimental 기능 등 주의해야 할 문제도 있다
Blitz.js, Preisma 및 Next가장 좋은 것은 먼저 js의 문서를 읽는 것이다.
각주
참조https://www.reddit.com/r/programminghorror/comments/66klvc/this_javascript_code_powers_a_1500_user_intranet/↩︎
@prisma/cli v2.9.0으로 실행↩︎
일부만 넣기↩︎
로그인하지 않은 사용자가 찰 수 있습니다. 악의적인 사용자가 로그인할 수 없으면 문제없습니다↩︎
취향에 따라 ajv↩︎로 교환 가능
Reference
이 문제에 관하여(Blitz.js에서 주의해야 할 것들(취약성 대책)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/rithmety/articles/20201102-blitzjs텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)