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.)