<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>セキュリティ対策 &#8211; ケケンタの独学ITブログ</title>
	<atom:link href="https://kekenta-it-blog.com/tag/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e5%af%be%e7%ad%96/feed/" rel="self" type="application/rss+xml" />
	<link>https://kekenta-it-blog.com</link>
	<description>プログラミングやWeb制作の情報を発信</description>
	<lastBuildDate>Tue, 18 Mar 2025 01:56:15 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://kekenta-it-blog.com/wp-content/uploads/2023/07/cropped-KEKENTA-BLOG-32x32.png</url>
	<title>セキュリティ対策 &#8211; ケケンタの独学ITブログ</title>
	<link>https://kekenta-it-blog.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【PHP】掲示板アプリの作り方｜正しいセキュリティ対策</title>
		<link>https://kekenta-it-blog.com/php-board-app-secure/</link>
		
		<dc:creator><![CDATA[ケケンタ]]></dc:creator>
		<pubDate>Mon, 18 Mar 2024 08:13:49 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webアプリ]]></category>
		<category><![CDATA[セキュリティ対策]]></category>
		<guid isPermaLink="false">https://kekenta-it-blog.com/?p=3549</guid>

					<description><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>以前にこちらの記事で掲示板アプリの作成方法を解説しました。 記事内でもお伝えしているように、上の記事で解説している掲示板アプリではセキュリティ対策はしておらず、本番運用には不向きの状態です。 今回は、この掲示板アプリにセ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__php-board-app-secure__3549-1024x576.jpg" class="webfeedsFeaturedVisual" /></p>
<p class="is-style-balloon_box2 wp-block-paragraph">以前にこちらの記事で<strong>掲示板アプリの作成方法</strong>を解説しました。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -external" data-type="type3" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">ケケンタの独学ITブログ</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/board-app-php/" target="_blank" rel="noopener noreferrer">掲示板アプリの作り方｜プログラミング初心者向け【PHP】 | ケケンタの独学ITブログ</a>
						<span class="p-blogCard__excerpt">初心者向けにPHPで掲示板アプリを作成する方法を解説しています。PHPの基礎学習後、初めてのWebアプリ開発におすすめの記事です。</span>					</div>
				</div>
			</div>
		</div>


<p class="wp-block-paragraph">記事内でもお伝えしているように、上の記事で解説している掲示板アプリでは<strong><span class="marker-under"><span class="swl-marker mark_orange">セキュリティ対策はしておらず、本番運用には不向き</span></span></strong>の状態です。</p>



<p class="wp-block-paragraph">今回は、この掲示板アプリに<strong>セキュリティ対策</strong>の処理を加え、それについて解説をしていきたいと思います。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>純粋な掲示板アプリの解説が読みたい場合、まずは<a href="https://kekenta-it-blog.com/board-app-php/">上記の記事</a>をご覧下さい！<br>その上で当記事の<strong>セキュリティ対策編</strong>をお読みいただくことでご自身でも安全なアプリケーション開発を行うポイントを学ぶことが可能です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<div class="swell-block-capbox cap_box is-style-shadow"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>この記事で分かること</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>XSS対策方法・攻撃内容</li>



<li>CSRF対策方法（トークンの利用）・攻撃内容</li>



<li>SQLインジェクション対策方法・攻撃内容</li>



<li>セッションハイジャック対策方法・攻撃内容</li>
</ul>
</div></div>



<p class="is-style-bg_stripe wp-block-paragraph">なお、この記事のセキュリティ対策は以下の書籍を参考にしています。<br>（<strong>通称：徳丸本</strong>と呼ばれる「Webアプリ開発者必読」とまで言われている書籍です）<br><br><a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDQgMkgzMGMtMS4xIDAtMiAuOS0yIDJzLjkgMiAyIDJoOS4yTDI0IDIxLjJjLS44LjgtLjggMiAwIDIuOHMyIC44IDIuOCAwTDQyIDguOFYxOGMwIDEuMS45IDIgMiAyczItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6Ij48L3BhdGg+PHBhdGggZD0iTTQxIDI3Yy0xLjEgMC0yIC45LTIgMnYxMGMwIDEuMS0uOSAyLTIgMkg5Yy0xLjEgMC0yLS45LTItMlYxMWMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDItLjkgMi0ycy0uOS0yLTItMkg5Yy0zLjMgMC02IDIuNy02IDZ2MjhjMCAzLjMgMi43IDYgNiA2aDI4YzMuMyAwIDYtMi43IDYtNlYyOWMwLTEuMS0uOS0yLTItMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsExternalLink" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span>体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践</a><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="47" aria-hidden="true" class="swl-inline-icon"> </span><br>徳丸 浩／著　SBクリエイティブ／出版│<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl">Amazon</a></p>


<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/alone-php-study/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">PHPはこうして習得した！約１年間の勉強内容【プログラミング独学】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<a href="https://kekenta-it-blog.com/php-deploy-xserver-for-zip/" class="c-blogLink -internal" data-style="text">
				<!-- <i class="c-blogLink__icon icon-link" role="presentation"></i> -->
				<span class="c-blogLink__icon">
					<svg xmlns="http://www.w3.org/2000/svg" class="swl-svg-link __svg" width="1em" height="1em" viewBox="0 0 48 48" role="img" aria-hidden="true" focusable="false"><path d="M21.2 30.2c-.5 0-1-.2-1.4-.6l-.7-.7c-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l7.1-7.1c2.3-2.3 5.3-3.5 8.5-3.5s6.2 1.2 8.5 3.5c4.7 4.7 4.7 12.3 0 17l-3.5 3.5c-.8.8-2 .8-2.8 0-.8-.8-.8-2 0-2.8l3.5-3.5c3.1-3.1 3.1-8.2 0-11.3-1.5-1.5-3.5-2.3-5.7-2.3-2.1 0-4.2.8-5.7 2.3l-7.1 7.1c-1.5 1.5-2.3 3.5-2.3 5.7s.8 4.2 2.3 5.7l.7.7c.8.8.8 2 0 2.8-.4.3-.9.5-1.4.5z" /><path d="M13.4 46.6c-3.1 0-6.1-1.2-8.5-3.5-2.3-2.3-3.5-5.3-3.5-8.5s1.2-6.2 3.5-8.5l3.5-3.5c.8-.8 2-.8 2.8 0 .8.8.8 2 0 2.8l-3.5 3.5c-1.5 1.5-2.3 3.5-2.3 5.7 0 2.1.8 4.2 2.3 5.7 3.1 3.1 8.2 3.1 11.3 0l7.1-7.1c1.5-1.5 2.3-3.5 2.3-5.7 0-2.1-.8-4.2-2.3-5.7l-.7-.7c-.8-.8-.8-2 0-2.8.8-.8 2-.8 2.8 0l.7.7c2.3 2.3 3.5 5.3 3.5 8.5s-1.2 6.2-3.5 8.5l-7.1 7.1c-2.3 2.3-5.3 3.5-8.4 3.5z" /></svg>				</span>
				<span class="c-blogLink__text">【PHP】エックスサーバーへデプロイする方法【初心者でも簡単！】</span>
			</a>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2025/03/eye-catch__school-php-and-wp__14099-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/school-php-and-wp/">PHPやWordPressを学ぶのにおすすめのプログラミングスクール【７選】</a>
						<span class="p-blogCard__excerpt">僕はこれまで独学でPHPを学習してきました。結論から言えば、それでもPHPを習得することはできました。 しかし、それに費やした累計学習期間は1年ほど。モチベーション&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h2 class="wp-block-heading">掲示板アプリの全体コード</h2>



<p class="is-style-balloon_box2 wp-block-paragraph"><strong>元々の掲示板アプリのコード</strong></p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-a10a9a3a-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-a10a9a3a-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-a10a9a3a-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する★
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理★
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-a10a9a3a-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-a10a9a3a-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p class="is-style-balloon_box2 wp-block-paragraph"><strong>セキュリティ対策を施したコード</strong></p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-61bcf5ce-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-61bcf5ce-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-61bcf5ce-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] =
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if(empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])){
        exit(&#39;不正な投稿です&#39;);
    }
    if(isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]);//トークン破棄
    if(isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]);//トークン破棄
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;?php 
            //★ 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo htmlspecialchars($post_item[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo htmlspecialchars($post_item[&#39;contributor_id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo htmlspecialchars($post_item[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo htmlspecialchars($post_item[&#39;created_at&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo htmlspecialchars($post_item[&#39;updated_at&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo htmlspecialchars($post_item[&#39;id&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])) : ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if (empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])) {
        exit(&#39;不正な投稿です&#39;);
    }
    if (isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]); //トークン破棄
    if (isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]); //トークン破棄
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;);
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo htmlspecialchars(&quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;, ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            
            &lt;?php 
            //★ 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_path&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    // ★【CSRF】トークンチェック
    if (empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])) {
        exit(&#39;不正な投稿です&#39;);
    }
    if (isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]); //トークン破棄
    if (isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]); //トークン破棄
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo htmlspecialchars($_SESSION[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo htmlspecialchars($_SESSION[&#39;comment&#39;], ENT_QUOTES, &#39;UTF-8&#39;); ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;?php 
            //★【CSRF】 不正リクエストチェック用のトークン生成
            $token = sha1(uniqid(mt_rand(), true));
            $_SESSION[&#39;board_token&#39;] = $token;
            echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
            ?&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-61bcf5ce-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-61bcf5ce-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p class="is-style-icon_info wp-block-paragraph">上記のコードの内、セキュリティ対策に関係しているコードには★マークを付けてあります。<br>ただし、XSS対策用のコードは記述箇所が多いため★マークは付けていません。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>その辺りも含め、これから詳しく解説をしていきます。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<h2 class="wp-block-heading">【解説】掲示板アプリで実施したセキュリティ対策</h2>



<p class="wp-block-paragraph">今回のコードでは、以下の<strong><span class="swl-marker mark_yellow">4種類のセキュリティ対策</span></strong>を実施しました。</p>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2"><div class="cap_box_ttl"><span><span data-icon="LsLightbulb" data-id="0" style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMzIgNDYuNUgxNmMtMS4xIDAtMi0uOS0yLTJzLjktMiAyLTJoMTZjMS4xIDAgMiAuOSAyIDJzLS45IDItMiAyek00MS43IDE1LjlDNDEuMyAxMyA0MCAxMC4zIDM4LjIgOCAzNC41IDMuMiAyOSAuOCAyMy4xIDEgMTQgMS40IDYuNSA4LjkgNiAxOGMtLjMgNiAyLjQgMTEuNyA3LjIgMTUuNC41LjQuOC45LjggMS41djEuNmMwIDIuMiAxLjggNCA0IDRoMTJjMi4yIDAgNC0xLjggNC00VjM1YzAtLjYuMy0xLjIuOS0xLjcgNS4zLTQgOC0xMC42IDYuOC0xNy40em0tNy4xIDEuN2gtLjNjLS43IDAtMS4zLS41LTEuNS0xLjItLjctMy4yLTMuMi01LjctNi40LTYuMy0uOC0uMS0xLjQtLjktMS4yLTEuN3MuOS0xLjQgMS43LTEuMmM0LjQuOCA4IDQuMiA4LjkgOC42LjEuOC0uNCAxLjYtMS4yIDEuOHoiPjwvcGF0aD48L3N2Zz4=)" aria-hidden="true" class="swl-inline-icon"> </span><strong>掲示板アプリに実施したセキュリティ対策</strong></span></div><div class="cap_box_content">
<ul class="wp-block-list is-style-check_list -list-under-dashed">
<li>XSS（クロスサイト・スクリプティング）</li>



<li>CSRF（クロスサイト・リクエスト・フォージェリ）</li>



<li>SQLインジェクション</li>



<li>セッションハイジャック</li>
</ul>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>それぞれのセキュリティ攻撃ついての詳しい解説は（セッションハイジャックを除き）以下の記事でまとめています。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__xss-php__961-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/xss-php/">【XSS】クロスサイト・スクリプティングとは？対策方法も解説【PHP】</a>
						<span class="p-blogCard__excerpt">今回はWebアプリにおけるセキュリティ攻撃の１つであるXSS（クロスサイト・スクリプティング）について解説をしていきます。  この記事を読むと分かること XSS（クロス&#8230;</span>					</div>
				</div>
			</div>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__csrf-php__918-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/csrf-php/">【CSRF】攻撃の流れやPHPでの対策方法を解説【クロスサイトリクエストフォージェリ】</a>
						<span class="p-blogCard__excerpt">Webサイトへのセキュリティ攻撃の１つにCSRF（クロスサイトリクエストフォージェリ）というものがあります。 この記事では、 CSRFの攻撃の流れ 攻撃による影響・被害 PH&#8230;</span>					</div>
				</div>
			</div>
		</div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__sql-inj-php__1106-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/sql-inj-php/">【PHP】SQLインジェクションの原因や攻撃手法【対策コード付き】</a>
						<span class="p-blogCard__excerpt">この記事ではセキュリティ攻撃の１つであるSQLインジェクションについて、その対策方法も含めて解説をしていきます。  この記事で分かること SQLインジェクション攻撃の&#8230;</span>					</div>
				</div>
			</div>
		</div>


<p class="wp-block-paragraph">とは言え、まったく知識が無いとプログラムコードを見ても何をしているのかイメージしづらくなってしまうため、各セキュリティ攻撃について簡単にご説明します。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h3 class="wp-block-heading">XSS（クロスサイト・スクリプティング）</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong>XSS（クロスサイト・スクリプティング）</strong>とは</span></div><div class="cap_box_content">
<p class="wp-block-paragraph"><strong>XSS（クロスサイト・スクリプティング）</strong>は、Webサイト内に悪意あるスクリプトを埋め込む攻撃です。</p>



<p class="wp-block-paragraph">例えば、悪意あるスクリプトが埋め込まれているサイトへユーザがアクセスしてしまうと、そのユーザのブラウザ上で悪意のあるスクリプトが実行され、個人情報漏洩などに繋がります。</p>



<p class="wp-block-paragraph">掲示板アプリで言うと、投稿内にスクリプトを埋め込まれるイメージです。</p>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ただ掲示板アプリを利用したいだけのユーザからしたら堪ったものではないですね……。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="wp-block-paragraph">詳しくは後述しますが</p>



<p class="is-style-big_icon_point wp-block-paragraph">XSS（クロスサイト・スクリプティング）対策のキーワードは「<strong>エスケープ処理</strong>」です。</p>



<h3 class="wp-block-heading">CSRF（クロスサイト・リクエスト・フォージェリ）</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong><strong>CSRF（クロスサイト・リクエスト・フォージェリ）</strong></strong>とは</span></div><div class="cap_box_content">
<p class="wp-block-paragraph"><strong>CSRF（クロスサイト・リクエスト・フォージェリ）</strong>は、悪意あるスクリプトが含まれているボタンやリンクをユーザにクリックさせることで、攻撃対象のサイトへ何らかの攻撃を仕掛けるセキュリティ攻撃です。</p>



<p class="wp-block-paragraph">例えば、迷惑メールのリンクをクリックした先に罠サイトがあり、その中のボタンなどを押下してしまうと、攻撃対象の掲示板サイトに不正投稿が行われてしまうといった攻撃です。</p>
</div></div>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/困った顔-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>ユーザからすると、例えば知らない内に「脅迫的内容の投稿」をしていたことになっていて、突然逮捕されてしまうといった事態になったりします。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="wp-block-paragraph">この対策を怠ると被害を被るのは運営者だけではないということですね。</p>



<p class="wp-block-paragraph">また、掲示板サイトでCSRF対策を怠ると、簡単に外部サイトから投稿することができてしまい、一般ユーザに多大な迷惑がかかります。</p>



<p class="wp-block-paragraph">詳しくは後述しますが</p>



<p class="is-style-big_icon_point wp-block-paragraph">CSRF攻撃へ有効な対策は「<strong>トークン認証</strong>」です。</p>



<h3 class="wp-block-heading">SQLインジェクション</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong><strong><strong>SQLインジェクション</strong></strong></strong>とは</span></div><div class="cap_box_content">
<p class="wp-block-paragraph"><strong>SQLインジェクション</strong>はデータベース処理の脆弱性をつき、不正なSQLを注入（インジェクション）することでログイン情報などを抜き取る攻撃手法です。</p>
</div></div>



<p class="wp-block-paragraph">本掲示板アプリでは個人情報は保持しない仕様ですが、SQLインジェクションを許容してしまうと最悪の場合、投稿内容をすべて削除されてしまう事態にもなりかねないため対策が欠かせません。</p>



<p class="wp-block-paragraph">ただ、実はこちらのSQLインジェクション対策については、元々の<strong>掲示板アプリ記事の時点ですでに処理が実装されています。</strong></p>



<p class="wp-block-paragraph">それに加えてPDOクラスを扱う際のオプションのひとつを追加しただけという形になります。</p>



<h3 class="wp-block-heading">セッションハイジャック</h3>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span><strong>セッションハイジャック</strong>とは</span></div><div class="cap_box_content">
<p class="wp-block-paragraph"><strong>セッションハイジャック</strong>は、文字通りセッションを乗っ取る攻撃手法です。</p>
</div></div>



<p class="wp-block-paragraph">本掲示板アプリではセッションを利用したユーザ識別を行ない、それにより編集や削除機能を有効化しています。</p>



<p class="wp-block-paragraph">つまり</p>



<p class="wp-block-paragraph">セッションを乗っ取られたら、簡単に投稿内容を編集されたり削除されたりしてしまい、ユーザが大きな被害を被ることになってしまいます。</p>



<p class="wp-block-paragraph">セッションハイジャックが起こる原因はいくつかありますが</p>



<p class="is-style-big_icon_point wp-block-paragraph">有効な対処法は「ページ遷移の度にセッションIDを刷新する」</p>



<p class="wp-block-paragraph">です。</p>



<p class="wp-block-paragraph">これにより、仮にセッションを一時的にでも乗っ取られてもページ遷移した際にセッションIDが新しくなるため、ハイジャックは解除されます。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【解説】セキュリティ対策ごとのソースコード</h2>



<p class="wp-block-paragraph">ここからは<strong><span class="swl-marker mark_yellow">実際のコードを見ながらセキュリティ対策について解説</span></strong>をしていきます。</p>



<h3 class="wp-block-heading">XSS（クロスサイト・スクリプティング）</h3>



<p class="wp-block-paragraph">まずはXSS対策からです。</p>



<p class="wp-block-paragraph">こちらの対策箇所は唯一★マークを付けていませんが、方法はシンプルで、<span><span class="marker-under" style=""><b>掲示板上で何かしら出力する部分に対してhtmlspecialchars</b></span></span><strong>関数</strong><strong><span class="marker-under">を利用</span>し、エスケープ処理を施しています。</strong></p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>htmlspecialchars($post_item[&#39;title&#39;], ENT_QUOTES, &#39;UTF-8&#39;);</code></pre></div>



<p class="wp-block-paragraph">こちらは、ユーザが掲示板へ投稿した<strong>投稿のタイトル（$post_item[&#8216;title]）を出力する箇所</strong>の記述です。</p>



<p class="wp-block-paragraph">通常であれば、<strong>$post_item[&#8216;title]</strong>と記述していたところに、htmlspecialcharsというPHPの関数で囲ってあげているという形です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>これにより、<strong>$post_item[&#8216;title]</strong>をエスケープ処理し、不正な入力値（スクリプト）が紛れていたとしてもそれをただの文字列として表示させる＝実行させないようにすることが可能です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="wp-block-paragraph">引数が後ろに２つ付いていますが、<strong>第二引数のENT_QUOTES</strong>はどの文字までをエスケープ対象とするかを表しています。</p>



<p class="wp-block-paragraph"><strong>第三引数</strong>は文字コードUTF-8を基準にエスケープするという意味です。</p>



<p class="is-style-alert-box has-box-style wp-block-paragraph">HTMLの文字形式（&lt;meta charset=&#8221;UTF-8&#8243;&gt;の部分）をUTF-8に指定することが推奨されます。指定しないと、攻撃者にUTF-8以外の別の文字コードに書き替えられ、htmlspecialchars関数を無効化されてしまう恐れがあります。</p>



<p class="wp-block-paragraph">以上が<strong>XSS対策</strong>です。</p>



<p class="is-style-good-box has-box-style is-style-big_icon_point wp-block-paragraph">何かしら出力する箇所はくまなくhtmlspecialchars関数でエスケープする</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__xss-php__961-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/xss-php/">【XSS】クロスサイト・スクリプティングとは？対策方法も解説【PHP】</a>
						<span class="p-blogCard__excerpt">今回はWebアプリにおけるセキュリティ攻撃の１つであるXSS（クロスサイト・スクリプティング）について解説をしていきます。  この記事を読むと分かること XSS（クロス&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">CSRF（クロスサイト・リクエスト・フォージェリ）</h3>



<p class="wp-block-paragraph">続くCSRFでのキーワードは「<strong>トークン認証</strong>」です。</p>



<div class="swell-block-capbox cap_box is-style-onborder_ttl2" data-colset="col3"><div class="cap_box_ttl"><span>トークン認証とは</span></div><div class="cap_box_content">
<p class="wp-block-paragraph">トークン認証とは、いわば合言葉で正しいリクエストかどうかを認証するということです。</p>
</div></div>



<p class="wp-block-paragraph">先ほど簡単にCSRFについてご説明をしましたが、CSRFでは攻撃対象のサイトへ不正リクエストを送信し、意図しない動作をさせます。</p>



<p class="wp-block-paragraph">つまり、<strong><span class="swl-marker mark_yellow">攻撃を受ける側でリクエストを正しく振り分けできていれば、この攻撃は阻止できる</span></strong>のです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>そこで使用するのが<strong>トークン</strong>と呼ばれるランダムな文字列です。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="wp-block-paragraph">これを実際の処理で見ると、以下のようなものになっています。</p>



<p class="is-style-balloon_box2 wp-block-paragraph">トークンを利用した処理</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php 
//★ 不正リクエストチェック用のトークン生成
$token = sha1(uniqid(mt_rand(), true));
$_SESSION[&#39;board_token&#39;] = $token;
echo &#39;&lt;input type=&quot;hidden&quot; name=&quot;board_token&quot; value=&quot;&#39;.$token.&#39;&quot; /&gt;&#39;;
&gt;</code></pre></div>



<p class="wp-block-paragraph">この処理は、「投稿ボタンform」の中に組み込まれています。</p>



<p class="wp-block-paragraph">つまり、投稿ボタンを押下すると、<span class="marker-under-red">①<strong>hidden属性で隠されたトークンが一緒にPOST送信</strong></span>されます。</p>



<p class="wp-block-paragraph">また、その直前で<span class="marker-under-red">②<strong>セッション変数に格納</strong></span>しています。</p>



<p class="wp-block-paragraph">そして、①と②を、<strong><span class="marker-under">実際に投稿処理を行う前に比較（以下の処理）し、一致すれば正しいリクエスト</span></strong>であると判断するという流れです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>// ★【CSRF】トークンチェック
if(empty($_SESSION[&#39;board_token&#39;]) || ($_SESSION[&#39;board_token&#39;] !== $_POST[&#39;board_token&#39;])){
    exit(&#39;不正な投稿です&#39;);
}
if(isset($_SESSION[&#39;board_token&#39;])) unset($_SESSION[&#39;board_token&#39;]);//トークン破棄
if(isset($_POST[&#39;board_token&#39;])) unset($_POST[&#39;board_token&#39;]);//トークン破棄</code></pre></div>



<p class="wp-block-paragraph">トークンは１回使用したらすぐに破棄します。</p>



<p class="wp-block-paragraph">理由は</p>



<p class="has-border -border03 wp-block-paragraph">トークンを何度も使い回す仕様にすると、トークン自体が盗まれた時点で攻撃が成立するようになってしまうため</p>



<p class="wp-block-paragraph">です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>合言葉に毎回異なるものを使用することでなりすましを防いでいるのです。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__csrf-php__918-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/csrf-php/">【CSRF】攻撃の流れやPHPでの対策方法を解説【クロスサイトリクエストフォージェリ】</a>
						<span class="p-blogCard__excerpt">Webサイトへのセキュリティ攻撃の１つにCSRF（クロスサイトリクエストフォージェリ）というものがあります。 この記事では、 CSRFの攻撃の流れ 攻撃による影響・被害 PH&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">SQLインジェクション</h3>



<p class="wp-block-paragraph">SQLインジェクション対策として追記しているのは以下の★マークの箇所です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP" data-line="[5,6,7]"><code>/**
 * DB接続処理
 */
$pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
    PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    PDO::ATTR_EMULATE_PREPARES =&gt; false,              // ★【SQLインジェクション】静的プレースホルダーを使用
]);</code></pre></div>



<p class="wp-block-paragraph">「静的プレースホルダーを使用」と書いてありますが、これを説明するにはまずプレースホルダーを理解していただく必要があります。</p>



<p class="wp-block-paragraph"><strong>プレースホルダー</strong>とは、以下の処理の部分のことです。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain" data-line="[7,8,12,13,14,15]"><code>/**
* 投稿内容登録処理
*/
$sql = (&#39;
    INSERT INTO
        board_info (title, comment, contributor_id)
    VALUES
        (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
    &#39;);
$stmt = $pdo-&gt;prepare($sql);
// プレースホルダーに値をセット
$stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
$stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
</code></pre></div>



<p class="wp-block-paragraph">注目して頂きたいのはハイライトされている箇所の「:」が付いている変数です。</p>



<p class="wp-block-paragraph">これがいわゆる<strong>プレースホルダー</strong>と呼ばれるもので、意味としては「一時的なスペース」です。</p>



<p class="wp-block-paragraph">なぜこのようなものを使用しているのかというと、プレースホルダーを間に挟むことで不正なSQLの実行を阻止することができるためです。</p>



<p class="wp-block-paragraph">詳しいご説明は割愛させて頂きますが、このプレースホルダーには<strong>静的</strong>と<strong>動的</strong>の2種類があり、静的プレースホルダーを利用すると、SQLの構造が確定するタイミングと実行タイミングの兼ね合いから、<strong><span class="marker-under">理論上SQLインジェクションが成功しなくなる</span></strong>のです。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>SQLインジェクションは、後からSQLの構造を無理やり変えることで不正な操作を行います。<br>しかし、静的プレースホルダーを利用すると、後から構造が変わることが無くなるため、SQLインジェクションが成立しなくなります。</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>


<p class="wp-block-paragraph">Webアプリケーションの仕様によっては動的プレースホルダーを利用する必要がある場合も出てくるのですが、そうでないのなら<strong><span class="marker-under">静的プレースホルダーを利用するのが確実</span></strong>です。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -internal" data-type="type2" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">あわせて読みたい</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2024/04/eye-catch__sql-inj-php__1106-300x169.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/sql-inj-php/">【PHP】SQLインジェクションの原因や攻撃手法【対策コード付き】</a>
						<span class="p-blogCard__excerpt">この記事ではセキュリティ攻撃の１つであるSQLインジェクションについて、その対策方法も含めて解説をしていきます。  この記事で分かること SQLインジェクション攻撃の&#8230;</span>					</div>
				</div>
			</div>
		</div>


<h3 class="wp-block-heading">セッションハイジャック</h3>



<p class="wp-block-paragraph">先ほど、セッションハイジャックの説明の中で、ページ遷移ごとにセッションIDを刷新することが対策になるとお伝えしました。</p>



<p class="wp-block-paragraph">それを行っているのが以下の箇所です。</p>



<div class="hcb_wrap"><pre class="prism line-numbers lang-plain" data-line="[9,10,11]"><code>/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
// ★【セッションハイジャック】セッションIDを新しいものに置き換える
session_regenerate_id();
</code></pre></div>



<p class="wp-block-paragraph"><strong>session_regenerate_id()</strong>関数は、セッションIDを新しいものと置き換える関数です。</p>



<p class="wp-block-paragraph">その際、セッションに元々格納済みのデータは維持されます。</p>


<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-4374558503914683"
     crossorigin="anonymous"></script>
<!-- ディスプレイ【横長】 -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-4374558503914683"
     data-ad-slot="9744298852"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>



<h2 class="wp-block-heading">【まとめ】正しいセキュリティ対策で安全なWebアプリケーション開発を</h2>



<p class="wp-block-paragraph">最後に改めて、セキュリティ対策を施した全体のコードを掲載します。</p>



<div class="swell-block-tab is-style-balloon has-border -border01" data-width-pc="auto" data-width-sp="auto"><ul class="c-tabList" role="tablist"><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="true" aria-controls="tab-159a1a47-0" data-onclick="tabControl">掲示板アプリ全体のコード</button></li><li class="c-tabList__item" role="presentation"><button role="tab" class="c-tabList__button" aria-selected="false" aria-controls="tab-159a1a47-1" data-onclick="tabControl">style.css</button></li></ul><div class="c-tabBody">
<div id="tab-159a1a47-0" class="c-tabBody__item" aria-hidden="false">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php（掲示板トップ）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {
    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);
    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);
    // SQL実行
    $stmt-&gt;execute();
    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;
    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;
    &lt;hr&gt;
    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">update-edit.php（編集画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 編集ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;update_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容取得処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 更新ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;update_submit_btn&#39;])) {
    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }
    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }
    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;
    /**
     * 必要項目がすべて入力されてたら更新処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容更新処理
             */
            $sql = (&#39;
                UPDATE board_info 
                SET title = :TITLE, comment = :COMMENT
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();
            // 更新に成功したらセッション変数を破棄
            // unset($_SESSION[&#39;id&#39;]);  // ※投稿IDは敢えて破棄せず、掲示板ページでID判定をするために情報を保持する★
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
            // 掲示板ページへ戻る
            header(&#39;Location: board.php&#39;);
            exit();
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    exit();
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;投稿編集画面&lt;/h1&gt;
    &lt;!-- 投稿編集フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;; ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;update_submit_btn&quot; value=&quot;update_submit_btn&quot;&gt;更新&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-confirm.php（削除確認画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;
/**
 * 削除ボタンで遷移してきたときの処理
 */
if (isset($_POST[&#39;delete_btn&#39;])) {
    /**
     * 編集対象の投稿情報を取得
     */
    if (isset($_POST[&#39;post_id&#39;]) && $_POST[&#39;post_id&#39;] != &#39;&#39;) {
        // セッションに投稿IDを保持
        $_SESSION[&#39;id&#39;] = $_POST[&#39;post_id&#39;];
        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);
            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                SELECT id, title, comment
                FROM board_info 
                WHERE id = :ID
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
            // SQL実行
            $stmt-&gt;execute();
            // 投稿情報の取得
            $post_info = $stmt-&gt;fetch();
            $_SESSION[&#39;title&#39;] = $post_info[&#39;title&#39;];
            $_SESSION[&#39;comment&#39;] = $post_info[&#39;comment&#39;];
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}
/**
 * 削除ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;delete_submit_btn&#39;])) {
    try {
        /**
         * DB接続処理
         */
        $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
            PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
        ]);
        /**
         * 投稿内容削除処理
         */
        $sql = (&#39;
            DELETE FROM board_info 
            WHERE id = :ID
        &#39;);
        $stmt = $pdo-&gt;prepare($sql);
        // プレースホルダーに値をセット
        $stmt-&gt;bindValue(&#39;:ID&#39;, $_SESSION[&#39;id&#39;], PDO::PARAM_INT);
        // SQL実行
        $stmt-&gt;execute();
        // 削除に成功したらセッション変数を破棄
        unset($_SESSION[&#39;id&#39;]);
        unset($_SESSION[&#39;title&#39;]);
        unset($_SESSION[&#39;comment&#39;]);
        // 削除成功画面へ遷移
        header(&#39;Location: delete-success.php&#39;);
        exit();
    } catch (PDOException $e) {
        echo &#39;接続失敗&#39; . $e-&gt;getMessage();
        exit();
    }
    // DBとの接続を切る
    $pdo = null;
    $stmt = null;
}
/**
 * キャンセルボタンが押下されたら
 * セッション情報を破棄して
 * 掲示板一覧画面へ戻る
 */
if (isset($_POST[&#39;cancel_btn&#39;])) {
    unset($_SESSION[&#39;id&#39;]);
    unset($_SESSION[&#39;title&#39;]);
    unset($_SESSION[&#39;comment&#39;]);
    header(&#39;Location: board.php&#39;);
    return;
}
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除確認&lt;/h1&gt;
    &lt;p class=&quot;delete-confirm-msg&quot;&gt;以下の投稿を削除します。&lt;/p&gt;
    &lt;!-- 削除確認画面 --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;p&gt;タイトル&lt;/p&gt;
                    &lt;p&gt;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;p&gt;投稿内容&lt;/p&gt;
                    &lt;p class=&quot;p-pre&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;]))  echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;btn-flex&quot;&gt;
                &lt;button type=&quot;submit&quot; name=&quot;delete_submit_btn&quot; value=&quot;delete_submit_btn&quot;&gt;削除&lt;/button&gt;
                &lt;button type=&quot;submit&quot; name=&quot;cancel_btn&quot; value=&quot;cancel_btn&quot;&gt;キャンセル&lt;/button&gt;
            &lt;/div&gt;
        &lt;/form&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>



<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">delete-success.php（削除成功画面）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php
/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();
/**
 * 掲示場TOPへ自動で遷移する処理★
 */
header(&#39;refresh: 3; url=board.php&#39;);
?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;削除が完了しました。&lt;/h1&gt;
    &lt;p class=&quot;delete-success-msg&quot;&gt;3秒後に自動で掲示板TOPへ戻ります。&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-159a1a47-1" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">style.css（同じ見た目にしたい方用）</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-css" data-lang="CSS"><code>body {
    margin: 0 auto;
    width: 700px;
    background-color: rgb(224, 224, 224);
}
hr {
    margin: 40px 0;
    border-color: rgb(137, 137, 137);
}
h1 {
    text-align: center;
}
li {
    list-style: none;
}
p {
    margin: 0;
}
p,
span {
    color: #333;
}
input,
textarea {
    padding: 10px;
    border: 1px solid gray;
    border-radius: 10px;
    width: 100%;
    box-sizing: border-box;
}
textarea {
    line-height: 1.5;
}
button {
    display: block;
    margin-top: 20px;
    padding: 10px 30px;
    color: #fff;
    border-radius: 10px;
    cursor: pointer;
}
button[name=&quot;post_btn&quot;] {
    border: 1px solid rgb(148, 148, 218);
    background-color: rgb(94, 94, 255);
}
button[name=&quot;update_btn&quot;],
button[name=&quot;update_submit_btn&quot;] {
    border: 1px solid rgb(62, 150, 62);
    background-color: rgb(74, 152, 74);
}
button[name=&quot;delete_btn&quot;],
button[name=&quot;delete_submit_btn&quot;] {
    border: 1px solid rgb(255, 31, 31);
    background-color: rgb(255, 48, 48);
}
button[name=&quot;cancel_btn&quot;] {
    border: 1px solid rgb(172, 172, 172);
    background-color: rgb(182, 182, 182);
}
button[name=&quot;post_btn&quot;]:hover {
    background-color: rgb(116, 116, 255);
}
button[name=&quot;update_btn&quot;]:hover,
button[name=&quot;update_submit_btn&quot;]:hover {
    background-color: rgb(83, 169, 83);
}
button[name=&quot;delete_btn&quot;]:hover,
button[name=&quot;delete_submit_btn&quot;]:hover {
    background-color: rgb(255, 82, 82);
}
button[name=&quot;cancel_btn&quot;]:hover {
    background-color: rgb(189, 189, 189);
}
.btn--mg-c {
    margin: 0 auto;
}
.post-list button {
    margin: 30px 0 0 0;
    padding: 8px 20px;
}
.post-list li {
    margin-bottom: 15px;
    padding: 20px 30px;
    background-color: #fff;
    border: 1px solid rgb(188, 188, 188);
    border-radius: 10px;
}
.post-list span {
    display: inline-block;
    margin-bottom: 25px;
}
.post-form__flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
    margin-bottom: 20px;
}
.post-form__flex&gt;div:first-child {
    width: 250px;
}
.post-form__flex&gt;div:last-child {
    flex: 1;
}
.btn-flex {
    display: flex;
    justify-content: center;
    column-gap: 15px;
}
.post-list li:last-child {
    margin-bottom: 0;
}
.post-datetime {
    display: inline-block;
    margin-top: 25px;
    font-size: 12px;
    color: gray;
}
.post-datetime__updated {
    display: inline-block;
    margin-left: 10px;
}
.updated-post {
    margin-left: auto;
    padding: 2px 5px;
    width: fit-content;
    font-size: 12px;
    border: 1px solid rgb(105, 105, 105);
    border-radius: 5px;
    color: rgb(105, 105, 105);
}
.no-post-msg {
    text-align: center;
}
.delete-confirm-msg {
    text-align: center;
    margin-bottom: 30px;
    color: red;
    font-weight: bold;
}
.delete-success-msg {
    text-align: center;
}
.err {
    color: red;
    font-size: 13px;
}
/* 
改行もそのまま表示するための指定
これが無いと改行が半角スペースに変換されて
表示されてしまう
 */
.p-pre {
    white-space: pre-wrap;
}</code></pre></div>
</div></details>
</div>
</div>



<div id="tab-159a1a47-2" class="c-tabBody__item" aria-hidden="true">
<div class="swell-block-accordion">
<details class="swell-block-accordion__item" data-swl-acc="wrapper"><summary class="swell-block-accordion__title" data-swl-acc="header"><span class="swell-block-accordion__label">board.php</span><span class="swell-block-accordion__icon c-switchIconBtn" data-swl-acc="icon" aria-hidden="true" data-opened="false"><i class="__icon--closed icon-caret-down"></i><i class="__icon--opened icon-caret-up"></i></span></summary><div class="swell-block-accordion__body" data-swl-acc="body">
<div class="hcb_wrap"><pre class="prism line-numbers lang-php" data-lang="PHP"><code>&lt;?php

/**
 * セッション開始
 * セッションの保存期間を1800秒に指定　※任意の秒数へ変更可能
 * かつ、確実に破棄する
 */
ini_set(&#39;session.gc_maxlifetime&#39;, 1800);
ini_set(&#39;session.gc_divisor&#39;, 1);
session_start();

/**
 * 投稿者ID（20桁）を生成
 */
if (isset($_SESSION[&#39;cont_id&#39;])) {
    $cont_id = $_SESSION[&#39;cont_id&#39;];
} else {
    $_SESSION[&#39;cont_id&#39;] = 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) .
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . chr(mt_rand(65, 90)) . 
        chr(mt_rand(65, 90)) . chr(mt_rand(65, 90));
    $cont_id = $_SESSION[&#39;cont_id&#39;];
}

/**
 * DB接続情報
 */
const DB_HOST = &#39;mysql:dbname=board;host=127.0.0.1;charset=utf8&#39;;
const DB_USER = &#39;kekenta&#39;;
const DB_PASSWORD = &#39;kekenta_pass&#39;;

/**
 * 投稿ボタンが押下されたときの処理
 */
if (isset($_POST[&#39;post_btn&#39;])) {

    // 更新操作用の処理
    unset($_SESSION[&#39;id&#39;]);

    /**
     * セッション変数に情報を保存して
     * タイトルまたは投稿内容の片方だけが
     * 入力されていた場合、
     * 入力フォームに内容を保持する
     */
    if (isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39;) {
        $_SESSION[&#39;title&#39;] = $_POST[&#39;post_title&#39;];
    } else {
        unset($_SESSION[&#39;title&#39;]);
    }

    if (isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;) {
        $_SESSION[&#39;comment&#39;] = $_POST[&#39;post_comment&#39;];
    } else {
        unset($_SESSION[&#39;comment&#39;]);
    }

    /**
     * エラーメッセージ格納
     */
    if ($_POST[&#39;post_title&#39;] == &#39;&#39;) $err_msg_title  = &#39;※タイトルを入力して下さい&#39;;
    if ($_POST[&#39;post_comment&#39;] == &#39;&#39;) $err_msg_comment  = &#39;※投稿内容を入力して下さい&#39;;

    /**
     * 必要項目がすべて入力されてたら投稿処理を実行
     */
    if (
        isset($_POST[&#39;post_title&#39;]) && $_POST[&#39;post_title&#39;] != &#39;&#39; &&
        isset($_POST[&#39;post_comment&#39;]) && $_POST[&#39;post_comment&#39;] != &#39;&#39;
    ) {
        $title = $_POST[&#39;post_title&#39;];
        $comment = $_POST[&#39;post_comment&#39;];

        try {
            /**
             * DB接続処理
             */
            $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
                PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
            ]);

            /**
             * 投稿内容登録処理
             */
            $sql = (&#39;
                INSERT INTO
                    board_info (title, comment, contributor_id)
                VALUES
                    (:TITLE, :COMMENT, :CONTRIBUTOR_ID)
            &#39;);
            $stmt = $pdo-&gt;prepare($sql);
            // プレースホルダーに値をセット
            $stmt-&gt;bindValue(&#39;:TITLE&#39;, $title, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:COMMENT&#39;, $comment, PDO::PARAM_STR);
            $stmt-&gt;bindValue(&#39;:CONTRIBUTOR_ID&#39;, $cont_id, PDO::PARAM_STR);
            // SQL実行
            $stmt-&gt;execute();

            // 投稿に成功したらセッション変数を破棄
            unset($_SESSION[&#39;title&#39;]);
            unset($_SESSION[&#39;comment&#39;]);
        } catch (PDOException $e) {
            echo &#39;接続失敗&#39; . $e-&gt;getMessage();
            exit();
        }
        // DBとの接続を切る
        $pdo = null;
        $stmt = null;
    }
}

/**
 * 投稿一覧取得処理
 */
try {
    /**
     * DB接続処理
     */
    $pdo = new PDO(DB_HOST, DB_USER, DB_PASSWORD, [
        PDO::ATTR_DEFAULT_FETCH_MODE =&gt; PDO::FETCH_ASSOC, // データをカラム名をキーとする連想配列で取得する
        PDO::ATTR_ERRMODE =&gt; PDO::ERRMODE_EXCEPTION,      // 例外が発生した際にスローする
    ]);

    $sql = (&#39;
        SELECT * 
        FROM board_info 
        ORDER BY id DESC
    &#39;);
    $stmt = $pdo-&gt;prepare($sql);

    // SQL実行
    $stmt-&gt;execute();

    // 投稿情報を辞書形式ですべて取得
    $post_list = $stmt-&gt;fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo &#39;接続失敗&#39; . $e-&gt;getMessage();
    exit();
}

?&gt;

&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;

&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;掲示板アプリ&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;./style.css&quot;&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;h1&gt;掲示板アプリ&lt;/h1&gt;

    &lt;!-- 投稿フォーム --&gt;
    &lt;section class=&quot;post-form&quot;&gt;
        &lt;form action=&quot;#&quot; method=&quot;post&quot;&gt;
            &lt;div class=&quot;post-form__flex&quot;&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;タイトル（※最大30文字）&lt;/p&gt;
                        &lt;input type=&quot;text&quot; name=&quot;post_title&quot; value=&quot;&lt;?php if (isset($_SESSION[&#39;title&#39;])) echo $_SESSION[&#39;title&#39;]; ?&gt;&quot;&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_title)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_title}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
                &lt;div&gt;
                    &lt;label&gt;
                        &lt;p&gt;投稿内容（※最大1000文字）&lt;/p&gt;
                        &lt;textarea name=&quot;post_comment&quot; cols=&quot;50&quot; rows=&quot;10&quot;&gt;&lt;?php if (isset($_SESSION[&#39;comment&#39;])) echo $_SESSION[&#39;comment&#39;]; ?&gt;&lt;/textarea&gt;
                        &lt;!-- エラーメッセージ --&gt;
                        &lt;?php if (isset($err_msg_comment)) {
                            echo &quot;&lt;p class=&#39;err&#39;&gt;{$err_msg_comment}&lt;/p&gt;&quot;;
                        } ?&gt;
                    &lt;/label&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;button class=&quot;btn--mg-c&quot; type=&quot;submit&quot; name=&quot;post_btn&quot; value=&quot;post_btn&quot;&gt;投稿&lt;/button&gt;
        &lt;/form&gt;
    &lt;/section&gt;

    &lt;hr&gt;

    &lt;!-- 投稿一覧 --&gt;
    &lt;section class=&quot;post-list&quot;&gt;
        &lt;?php if (count($post_list) === 0) : ?&gt;
            &lt;!-- 投稿が無いときはメッセージを表示する --&gt;
            &lt;p class=&quot;no-post-msg&quot;&gt;現在、投稿はありません。&lt;/p&gt;
        &lt;?php else : ?&gt;
            &lt;ul&gt;
                &lt;!-- 投稿情報の出力 --&gt;
                &lt;?php foreach ($post_list as $post_item) : ?&gt;
                    &lt;li&gt;
                        &lt;form action=&quot;&quot; method=&quot;post&quot;&gt;
                            &lt;!-- 投稿ID --&gt;
                            &lt;span&gt;ID：&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;　&lt;/span&gt;
                            &lt;!-- 投稿タイトル --&gt;
                            &lt;span&gt;&lt;?php echo $post_item[&#39;title&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿者ID --&gt;
                            &lt;span&gt;／投稿者：&lt;?php echo $post_item[&#39;contributor_id&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 投稿内容 --&gt;
                            &lt;p class=&quot;p-pre&quot;&gt;&lt;?php echo $post_item[&#39;comment&#39;]; ?&gt;&lt;/p&gt;
                            &lt;!-- 投稿日時 --&gt;
                            &lt;span class=&quot;post-datetime&quot;&gt;投稿日時：&lt;?php echo $post_item[&#39;created_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;!-- 過去に更新されていたら更新日時も表示 --&gt;
                            &lt;?php if ($post_item[&#39;created_at&#39;] &lt; $post_item[&#39;updated_at&#39;]) : ?&gt;
                                &lt;span class=&quot;post-datetime post-datetime__updated&quot;&gt;更新日時：&lt;?php echo $post_item[&#39;updated_at&#39;]; ?&gt;&lt;/span&gt;
                            &lt;?php endif; ?&gt;
                        &lt;/form&gt;
                        &lt;!-- 自分の投稿内容かつセッションが有効な間は編集・削除が可能 --&gt;
                        &lt;?php if ($post_item[&#39;contributor_id&#39;] === $cont_id) : ?&gt;
                            &lt;div class=&quot;btn-flex&quot;&gt;
                                &lt;form action=&quot;update-edit.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;update_btn&quot;&gt;編集&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                                &lt;form action=&quot;delete-confirm.php&quot; method=&quot;post&quot;&gt;
                                    &lt;button type=&quot;submit&quot; name=&quot;delete_btn&quot;&gt;削除&lt;/button&gt;
                                    &lt;input type=&quot;hidden&quot; name=&quot;post_id&quot; value=&quot;&lt;?php echo $post_item[&#39;id&#39;]; ?&gt;&quot;&gt;
                                &lt;/form&gt;
                            &lt;/div&gt;
                        &lt;?php endif; ?&gt;
                        &lt;?php if (isset($_SESSION[&#39;id&#39;]) && ($_SESSION[&#39;id&#39;] == $post_item[&#39;id&#39;])): ?&gt;
                            &lt;p class=&#39;updated-post&#39;&gt;更新しました&lt;/p&gt;
                        &lt;?php endif; ?&gt;
                    &lt;/li&gt;
                &lt;?php endforeach; ?&gt;
            &lt;/ul&gt;
        &lt;?php endif; ?&gt;
    &lt;/section&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre></div>
</div></details>
</div>
</div>
</div></div>



<p class="wp-block-paragraph">今回は前回こちらの記事で解説をした掲示板アプリにおける<strong>セキュリティ対策</strong>について解説をしてきました。</p>


<div class="swell-block-postLink">			<div class="p-blogCard -external" data-type="type3" data-onclick="clickLink">
				<div class="p-blogCard__inner">
					<span class="p-blogCard__caption">ケケンタの独学ITブログ</span>
					<div class="p-blogCard__thumb c-postThumb"><figure class="c-postThumb__figure"><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/11/eye-catch__board-app-php__2739.jpg" alt="" class="c-postThumb__img u-obf-cover" width="320" height="180"></figure></div>					<div class="p-blogCard__body">
						<a class="p-blogCard__title" href="https://kekenta-it-blog.com/board-app-php/" target="_blank" rel="noopener noreferrer">掲示板アプリの作り方｜プログラミング初心者向け【PHP】 | ケケンタの独学ITブログ</a>
						<span class="p-blogCard__excerpt">初心者向けにPHPで掲示板アプリを作成する方法を解説しています。PHPの基礎学習後、初めてのWebアプリ開発におすすめの記事です。</span>					</div>
				</div>
			</div>
		</div>


<p class="wp-block-paragraph">しかし、実を言うと</p>



<p class="has-border -border03 wp-block-paragraph">セキュリティ対策に100%は無く、<strong>できるだけ防御率を100%に近づける</strong>という考え方が正しい</p>



<p class="wp-block-paragraph">です。</p>



<p class="wp-block-paragraph">また、<strong><span class="marker-under">アプリの仕様によって取るべき対策は異なります。</span></strong>そのため、セキュリティ対策の知識はある意味プログラミング言語の学習よりも重要で大変なものだったりします。</p>



<p class="wp-block-paragraph">僕は以下の書籍（通称「徳丸本」と呼ばれるWeb開発者必携の書籍です）を参考に、いつもWebアプリ開発をしています。</p>


<div id="rinkerid3655" class="yyi-rinker-contents  yyi-rinker-postid-3655 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" data-vars-click-id="rakuten_img 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/3163/9784797393163.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" data-vars-amp-click-id="rakuten_title 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]" >体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,520</span>
															<span class="price_at">(2026/05/25 04:06:24時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88%EF%BC%BB%E5%9B%BA%E5%AE%9A%E7%89%88%EF%BC%BD-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8-%E6%B5%A9-ebook/dp/B07DVY4H3M?_encoding=UTF8&amp;dib_tag=se&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFijL3FSdFSR0LKwwn0F-UPgnO4-c3ozCV4u_yzlUP10v8KPCWYU6aPhFknUSSGvFmOEDGJ7u_LQxIZPLfydTHs_AWTWMCbT_FAR33FxKzQdND0le-SUmRnBHzYhR8SX_lsohxpGeQkIATYHxCJlB0aHhgwHHQ_THHRbyVElNccJqEMDb7ELZa0F--eVduuVxaejEJv9h9ZmItplRO6lE6VyZJA2Jej7Jvd7bD0ypm9krDwLy3e-Ea8YDtZc7KF66Cb-ea0Tp3FGBrFX0K3fiRlfA.KN6w39aSpN4iCwmHQ6974qNXMN0yNo0Ib071kV4gNk4&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=3aee57ca3ac28d84506bf0e0db6cec11&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="amazon_kindle 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFijL3FSdFSR0LKwwn0F-UPgnO4-c3ozCV4u_yzlUP10v8KPCWYU6aPhFknUSSGvFmOEDGJ7u_LQxIZPLfydTHs_AWTWMCbT_FAR33FxKzQdND0le-SUmRnBHzYhR8SX_lsohxpGeQkIATYHxCJlB0aHhgwHHQ_THHRbyVElNccJqEMDb7ELZa0F--eVduuVxaejEJv9h9ZmItplRO6lE6VyZJA2Jej7Jvd7bD0ypm9krDwLy3e-Ea8YDtZc7KF66Cb-ea0Tp3FGBrFX0K3fiRlfA.KN6w39aSpN4iCwmHQ6974qNXMN0yNo0Ib071kV4gNk4&amp;dib_tag=se&amp;keywords=%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3&amp;qid=1723712376&amp;sr=8-1&amp;linkCode=ll1&amp;tag=https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E4%B8%8A-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB/dp/4297114682?dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;dib_tag=se&amp;keywords=PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=16a4b7edeeedcc86aef9f0b8c45cc669&amp;language=ja_JP&amp;ref_=as_li_ss_tl-22&amp;linkId=04fec4999f3ec4094bf4fd1126da8b84&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="amazon 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325051043?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F15472730%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F19130417%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]"  data-vars-amp-click-id="rakuten 3655 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 [ 徳丸 浩 ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>



<p class="is-style-bg_stripe wp-block-paragraph"><a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl"><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNNDQgMkgzMGMtMS4xIDAtMiAuOS0yIDJzLjkgMiAyIDJoOS4yTDI0IDIxLjJjLS44LjgtLjggMiAwIDIuOHMyIC44IDIuOCAwTDQyIDguOFYxOGMwIDEuMS45IDIgMiAyczItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6Ij48L3BhdGg+PHBhdGggZD0iTTQxIDI3Yy0xLjEgMC0yIC45LTIgMnYxMGMwIDEuMS0uOSAyLTIgMkg5Yy0xLjEgMC0yLS45LTItMlYxMWMwLTEuMS45LTIgMi0yaDEwYzEuMSAwIDItLjkgMi0ycy0uOS0yLTItMkg5Yy0zLjMgMC02IDIuNy02IDZ2MjhjMCAzLjMgMi43IDYgNiA2aDI4YzMuMyAwIDYtMi43IDYtNlYyOWMwLTEuMS0uOS0yLTItMnoiPjwvcGF0aD48L3N2Zz4=)" data-icon="LsExternalLink" data-id="1" aria-hidden="true" class="swl-inline-icon"> </span>体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践</a><span style="--the-icon-svg: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjFlbSIgd2lkdGg9IjFlbSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBhcmlhLWhpZGRlbj0idHJ1ZSIgdmlld0JveD0iMCAwIDQ4IDQ4Ij48cGF0aCBkPSJNMTEuNyAxLjQgNi44IDVjLS41LjQtLjggMS0uOCAxLjZ2MjguN2MwIC44LjUgMS41IDEuMiAxLjhsMjQgMTAuM2MxLjMuNiAyLjgtLjQgMi44LTEuOFYxOWMwLS44LS41LTEuNS0xLjItMS44TDEwLjIgNy41bDIuOS0yLjJjLjktLjYgMi0uOCAzLS40bDIwLjYgOC44Yy43LjMgMS4yIDEgMS4yIDEuOFY0Mi45YzAgLjkgMSAxLjMgMS43LjhsMS43LTEuNWMuNC0uNC43LS45LjctMS41VjEzYzAtLjgtLjUtMS41LTEuMi0xLjhMMTYuNy44Yy0xLjctLjctMy42LS41LTUgLjZ6Ij48L3BhdGg+PC9zdmc+)" data-icon="LsBook" data-id="47" aria-hidden="true" class="swl-inline-icon"> </span><br>徳丸 浩／著　SBクリエイティブ／出版│<a href="https://www.amazon.co.jp/%E4%BD%93%E7%B3%BB%E7%9A%84%E3%81%AB%E5%AD%A6%E3%81%B6-%E5%AE%89%E5%85%A8%E3%81%AAWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E4%BD%9C%E3%82%8A%E6%96%B9-%E7%AC%AC2%E7%89%88-%E8%84%86%E5%BC%B1%E6%80%A7%E3%81%8C%E7%94%9F%E3%81%BE%E3%82%8C%E3%82%8B%E5%8E%9F%E7%90%86%E3%81%A8%E5%AF%BE%E7%AD%96%E3%81%AE%E5%AE%9F%E8%B7%B5-%E5%BE%B3%E4%B8%B8/dp/4797393165?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&amp;crid=1FQAOXKEGI9HT&amp;dib=eyJ2IjoiMSJ9.ksxMxdA4KTXnYLFgVxMFis4f3XHMUvarmNijcsU4Nmvl3Tud_nU0g7agEl3ercb-Os7uj_I-9w5xejzyw_JwMcs7FC4uVP9jc3sHC7c9ZuDT_gwuJFliueZNV3zuXq4731v-JAlEh4pR64KI-_puhFly0i_zkfDlsH2xTLQWoeNNIM9FkS584d43eeD8-mNtPjbtKK1lmvjecUb-VALfXImg-mACYpqlPWhTawzlYmnCmT85BL5k4gVzrtlErnyRPeFE4qCXwaN884rSGk9l6PGCfVcIoDQOg1lp8Ia-RWA.i4wIGc7KFczkxeNgrmVo03tuk6Fod-K6t-LEHGJtLtE&amp;dib_tag=se&amp;keywords=Web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3&amp;qid=1718235109&amp;sprefix=web%E3%82%A2%E3%83%97%E3%83%AA+%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%2Caps%2C186&amp;sr=8-1&amp;linkCode=ll1&amp;tag=kekenta03amaz-22&amp;linkId=dc5df2a77d4a028f4519e6b2a07ffb84&amp;language=ja_JP&amp;ref_=as_li_ss_tl">Amazon</a></p>



<p class="wp-block-paragraph">それでも本当に対策ができているのか不安なので、色々なネット記事も参考にしながら開発をしています。</p>



<p class="wp-block-paragraph">セキュリティ攻撃は残念なことに日々新しい手法が誕生していっている分野なので、開発する側もしっかりと学習を継続することが大切です。</p>


<div class="swell-block-balloon"><div class="c-balloon -bln-left" data-col="gray"><div class="c-balloon__icon -circle"><img decoding="async" src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" data-src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="lazyload c-balloon__iconImg" width="80px" height="80px"><noscript><img decoding="async" src="https://kekenta-it-blog.com/wp-content/uploads/2023/07/キリッ-150x150.jpg" alt="" class="c-balloon__iconImg" width="80px" height="80px"></noscript><span class="c-balloon__iconName">ケケンタ</span></div><div class="c-balloon__body -speaking -border-on"><div class="c-balloon__text">
<p>それでは本記事は以上とさせていただきます。<br>最後までお読みいただきありがとうございました！</p>
<span class="c-balloon__shapes"><span class="c-balloon__before"></span><span class="c-balloon__after"></span></span></div></div></div></div>

<div id="rinkerid3653" class="yyi-rinker-contents  yyi-rinker-postid-3653 yyi-rinker-img-m yyi-rinker-catid-5 yyi-rinker-catid-72 ">
	<div class="yyi-rinker-box">
		<div class="yyi-rinker-image">
							<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_i_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking"  data-click-tracking="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-click-id="rakuten_img 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"><img decoding="async" src="https://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4688/9784297114688.jpg?_ex=128x128"  width="128" height="128" class="yyi-rinker-main-img" style="border: none;"></a>					</div>
		<div class="yyi-rinker-info">
			<div class="yyi-rinker-title">
									<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&#038;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&#038;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-tracking" data-click-tracking="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" data-vars-amp-click-id="rakuten_title 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]" >PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]</a>							</div>
			<div class="yyi-rinker-detail">
							<div class="credit-box">created by&nbsp;<a href="https://oyakosodate.com/rinker/" rel="nofollow noopener" target="_blank" >Rinker</a></div>
										<div class="price-box">
							<span title="" class="price">¥3,938</span>
															<span class="price_at">(2026/05/25 07:29:17時点&nbsp;楽天市場調べ-</span><span title="このサイトで掲載されている情報は当サイトの作成者により運営されています。価格、販売可能情報は、変更される場合があります。購入時に楽天市場店舗（www.rakuten.co.jp）に表示されている価格がその商品の販売に適用されます。">詳細)</span>
																	</div>
						</div>
						<ul class="yyi-rinker-links">
																	<li class="amazonkindlelink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80%EF%BC%BB%E4%B8%8A%EF%BC%BD-%EF%BD%9E%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB-ebook/dp/B08DXRK18C?_encoding=UTF8&amp;dib_tag=se&amp;dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=8de435cc399443bbfb43b9e7b8e0c9f1&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon_kindle 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Kindle</a>					</li>
								                    <li class="amazonlink">
						<a href="https://www.amazon.co.jp/PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E4%B8%8A-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%81%A8%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E9%80%A3%E6%90%BA%E3%81%BE%E3%81%A7-%E5%A4%A7%E5%AE%B6-%E6%AD%A3%E7%99%BB/dp/4297114682?dib=eyJ2IjoiMSJ9.74YDItYNn-AHro6XQ1cSslRSHUvp_S8S4MVJtvnW_XswliMGieYQktGbaTJY9E-Qpy3y3roMKB8M-zKI3K7otpqjDxkuoq7ncq-6mLf3BEkcNW05BAHDZZ17WZueAniDY7peSrmp4Ji0L0BkXOaJIBbpqa628I6bjQBED1FQ9V7BJqUJVUUxz6ns2GIHnoSItDTgCRaIpNi9fMcBrt3jqZr1qNJxCmBn8-xPR9N3usFpENEEChvMwvGdHoHu1hjsq6g9GvJDwPPBTwhQvDgXG2KZQ5CBlEx_wQjQy06hFcw.xxCKw6aGhA397JIEATXvL3RNC7D4_k4avRIYczzkjHw&amp;dib_tag=se&amp;keywords=PHP%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80&amp;qid=1723712413&amp;sr=8-6&amp;linkCode=ll1&amp;tag=kekenta03am0b-22&amp;linkId=16a4b7edeeedcc86aef9f0b8c45cc669&amp;language=ja_JP&amp;ref_=as_li_ss_tl" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="amazon 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">Amazon</a>					</li>
													<li class="rakutenlink">
						<a href="https://hb.afl.rakuten.co.jp/hgc/g00q072g.bdzz22a5.g00q072g.bdzz326e/Rinker_t_20240325050010?pc=https%3A%2F%2Fitem.rakuten.co.jp%2Fbook%2F16371381%2F&amp;m=http%3A%2F%2Fm.rakuten.co.jp%2Fbook%2Fi%2F20055321%2F&amp;rafcid=wsc_i_is_1047822029026699702" rel="nofollow" class="yyi-rinker-link yyi-rinker-tracking"  data-click-tracking="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]"  data-vars-amp-click-id="rakuten 3653 PHP本格入門［上］　～プログラミングとオブジェクト指向の基礎からデータベース連携まで [ 大家正登 ]">楽天市場</a>					</li>
								                											</ul>
					</div>
	</div>
</div>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
