データベースへの接続が、ORA-01017「ユーザー名/パスワードが無効です」で拒否された…。
単純な入力ミスであれば、正しいパスワードを入れ直せば解決します。
しかし、入力を何度見直しても間違いが見つからないことがあります。
ORA-01017 の原因は、パスワードの誤りだけではありません。
ユーザー名の誤り・大文字小文字の違い・OS 認証の失敗まで、複数の原因が同じメッセージになります。
そして、そのどれに当たるのかは、エラーメッセージからは判別できません。
今回は、Oracle Database 19c の実機で ORA-01017 になる原因を1つずつ再現し、切り分けの型を整理します。
具体的には、次の3点を実機ログで確認します。
- 複数の原因が同じ ORA-01017 になり、出力からは区別できないこと
- 同じログイン失敗でも、別の番号(ORA-28000・ORA-28001・ORA-01045)で返る条件
- 接続を試す前に、dba_users ビューで状態を読む方法
1. 症状
データベースへの接続時に、次のエラーで拒否されます。
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。メッセージは「ユーザー名/パスワードが無効です」と示すだけで、ユーザー名とパスワードのどちらが間違っているのかは分かりません。
この段階では、単純な入力ミスなのか、それ以外の原因なのかも切り分けられません。
※先頭のゼロを省いて ORA-1017 と表記されることもありますが、同じエラーを指します。
2. 原因の仕組み
ORA-01017 は「認証に失敗した」という結果だけを返すエラーです。
エラーメッセージには、ユーザー名とパスワードのどちらが間違っているかの情報が含まれていません。
これは、調査する側から見ると不親切なエラーです。
しかし、セキュリティの視点で見ると理にかなっています。
もし「ユーザーが存在しません」と「パスワードが違います」を区別して返すと、ログインを試すだけで「そのユーザー名が実在するかどうか」が外部から分かってしまいます。
実在するユーザー名の一覧は、攻撃者にとってパスワードを試す対象のリストそのものです。
このため、認証に失敗した理由を明かさないことは、ログイン機能を持つシステムに共通するセキュリティ設計になっています(ユーザー名の列挙と呼ばれる調査手法への対策)。
Oracle がこの意図を明文化しているわけではありませんが、ORA-01017 の動作もこの設計に沿ったもので、どちらが間違いかを示さないこと自体がアカウントを守る動作と言えます。
実際、次の原因はすべて同じ ORA-01017 になります。
| # | 原因 | 状況の例 |
|---|---|---|
| 1 | パスワードの誤り | 入力ミス・変更後の古いパスワードを使用 |
| 2 | ユーザー名の誤り | 存在しないユーザー名を指定 |
| 3 | パスワードの大文字小文字 | 文字の並びは正しいが大文字小文字が異なる |
| 4 | 引用符付きで作成されたユーザー名 | "user" と小文字で作られたユーザーに引用符なしで接続 |
| 5 | OS 認証の失敗 | OSDBA グループに属さない OS ユーザーで / as sysdba を実行 |
| 6 | パスワードバージョンの不一致 | 古いクライアントからの接続だけが失敗する |
パスワードの誤りとユーザー名の誤りは、入力側の単純な誤りです。
一方、大文字小文字の違いから下の4つは本人が間違いに気づきにくい原因で、「何度見直しても間違いが見つからない」状況の多くはここに含まれます。
そして、どちらの場合も出力される ORA-01017 は同じです。
原因が1つに絞れない以上、ORA-01017 の対処は「思い当たる原因を上から順に試す」になりがちです。
しかし、その前に確認すべきことがあります。
同じ「ログインできない」でも、原因によっては ORA-01017 ではない別の番号が返るためです。
まず、出ているエラーが本当に ORA-01017 かを確認して調査の範囲を絞り、その上でパスワード・ユーザー名・大文字小文字を順に疑います。
なお、ORA-01017 が出ているということは、接続要求はデータベースまで到達しています。
接続先にたどり着けない段階のエラー(ORA-12154 や ORA-12541 など)とは層が異なり、接続設定側の調査は不要です。
次の章から、表の原因を実機で1つずつ再現します。
3. 同じ ORA-01017 になる原因を実機で再現する
この章では、「原因の仕組み」の章で挙げた原因を実機で順に再現します。
単純な誤り(パスワードの間違い・ユーザー名の間違い)から始めて、気づきにくい原因(大文字小文字・引用符付きユーザー・OS 認証)へ進みます。
残るパスワードバージョンの不一致だけは、再現に古いクライアント環境が必要なため、「接続を試す前に dba_users で状態を読む」の章で確認ポイントとして取り上げます。
3-1. 検証環境
検証は次の環境で行いました。
- Oracle Database 19c Enterprise Edition・非CDB構成(バージョンは 19.28。四半期ごとの更新パッチ=RU の適用後番号です)
- Oracle Linux 8・SQL*Plus 19c(エラーメッセージは日本語表示の設定)
検証用に、CREATE SESSION 権限のみを付与したユーザー TS01017 を作成し、状態を変えながら接続を試します。
3-2. 正しい資格情報でログインできる状態を作る
失敗の再現に入る前に、正しいユーザー名・正しいパスワードならログインできることを確認しておきます。
この後の検証はすべて、この成功する状態から条件を1つだけ変えて失敗させる形で進めます。
先に、検証ユーザーの前提を整理しておきます。
ユーザー名は ts01017、パスワードは Ts01017#Lab(11文字)です。
本記事では、CREATE USER でも CONNECT でも、パスワードを二重引用符で囲んで指定します。
この二重引用符は「ここからここまでがパスワード」という区切りの記号で、パスワードの一部ではありません(そもそもパスワードに二重引用符という文字自体は使えません)。
囲むことが必須なのは、パスワードがアルファベット以外の文字で始まる場合や、英数字と _ $ # 以外の文字を含む場合です(『Oracle Database SQL言語リファレンス』の CREATE USER の節にある規則です)。
それ以外では任意ですが、記号入りのパスワードでは常に囲むのが確実です。
SQL> CREATE USER ts01017 IDENTIFIED BY "Ts01017#Lab";
ユーザーが作成されました。
SQL> GRANT CREATE SESSION TO ts01017;
権限付与が成功しました。作成したユーザーで接続します。
SQL> CONNECT ts01017/"Ts01017#Lab"
接続されました。
SQL> SHOW USER
ユーザーは"TS01017"です。正しい資格情報で接続できることを確認できました。
ここで1点、後の検証につながる出力があります。
ユーザーは小文字の ts01017 で作成したのに、SHOW USER には大文字の “TS01017” と表示されています。
引用符を付けずに書いたユーザー名は、大文字に変換されて登録されるためです。
この挙動は「引用符付きで作成されたユーザー名」の検証で改めて取り上げます。
3-3. パスワードの誤り
まず、単純な誤りの1つ目、パスワードの間違いです。
実在するユーザー ts01017 に、間違ったパスワードで接続します。
SQL> CONNECT ts01017/"WrongPass#99"
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
警告: Oracleにはもう接続されていません。ORA-01017 で拒否されました。
なお、最後の「警告: Oracleにはもう接続されていません。」は SQL*Plus の注意点です。
SQL*Plus の中で CONNECT に失敗すると、元のセッションに戻るのではなく、それまでの接続も切れて未接続の状態になります。
失敗した後にそのまま SELECT などを実行するとエラーになるため、接続し直してから作業を続けます。
3-4. ユーザー名の誤り(出力は区別できない)
次に、単純な誤りのもう1つ、ユーザー名の間違いです。
作成していないユーザー名 nouser01017 で接続します。
存在しないユーザー名なので、パスワードは何であっても結果は変わりません。
SQL> CONNECT nouser01017/"whatever123"
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
警告: Oracleにはもう接続されていません。「ユーザーが存在しません」とは表示されず、パスワード誤りのとき(前の検証)と一字一句同じ出力が返りました。
2つの出力を見比べても、ユーザー名が違うのかパスワードが違うのかを判別する方法はありません。
これが「原因の仕組み」の章で述べた、失敗の理由を区別しない動作の実際の見え方です。
3-5. パスワードの大文字小文字
ここからは、本人が間違いに気づきにくい原因です。
1つ目は、大文字小文字の違いです。
正しいパスワードは Ts01017#Lab(先頭が大文字)ですが、これをすべて小文字で入力します。
SQL> CONNECT ts01017/"ts01017#lab"
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
警告: Oracleにはもう接続されていません。文字の並びは完全に正しくても、大文字小文字が1文字でも異なれば ORA-01017 です。
19c では、デフォルトでパスワードの大文字と小文字が区別されます。
「パスワードは絶対に合っているのに拒否される」と感じたときは、Caps Lock の状態や、パスワード管理ツールからのコピーで大文字小文字が変わっていないかを確認します。
3-6. 引用符付きで作成されたユーザー名
今度は、同じことがユーザー名側で起きる例です。
先ほどの SHOW USER で見たとおり、引用符なしのユーザー名は大文字に変換されて登録されます。
逆に、二重引用符で囲んで作成すると、小文字のまま登録されます。
小文字のままのユーザーを作成します。
SQL> CREATE USER "ts01017q" IDENTIFIED BY "Ts01017#Lab";
ユーザーが作成されました。
SQL> GRANT CREATE SESSION TO "ts01017q";
権限付与が成功しました。このユーザーに、引用符なしで接続します。
SQL> CONNECT ts01017q/"Ts01017#Lab"
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
警告: Oracleにはもう接続されていません。パスワードは正しいのに、ORA-01017 で拒否されました。
引用符なしで書いた ts01017q は大文字の TS01017Q として扱われ、実在するのは小文字の ts01017q だけなので、「存在しないユーザー」と同じ扱いになるためです。
同じユーザー名を、二重引用符で囲んで接続します。
SQL> CONNECT "ts01017q"/"Ts01017#Lab"
接続されました。同じユーザー・同じパスワードでも、引用符の有無だけで成否が分かれました。
登録されているユーザー名を、データディクショナリの DBA_USERS ビュー(データベースの全ユーザーの登録情報を保持するビュー)で確認します。
DBA_USERS は一般ユーザーからは参照できない DBA 向けのビューのため、SYSDBA に接続し直してから照会します。
SQL> CONNECT / AS SYSDBA
接続されました。
SQL> COLUMN username FORMAT a20
SQL> SELECT username FROM dba_users WHERE username IN ('TS01017Q', 'ts01017q');
USERNAME
--------------------
ts01017q実在するのは小文字の ts01017q の1行だけで、大文字の TS01017Q は存在しません。
引用符なしの名前が「別のユーザー」として扱われていることは、もう1つの操作で確かめられます。
この状態のまま、引用符なしの ts01017q でユーザーを作成してみます。
SQL> CREATE USER ts01017q IDENTIFIED BY "Ts01017#Lab";
ユーザーが作成されました。見た目は同じ名前なのに、既存ユーザーとの重複エラーにならず作成できました。
dba_users を確認すると、大文字の TS01017Q と小文字の ts01017q が、別のユーザーとして2行並んでいます。
SQL> SELECT username FROM dba_users WHERE username IN ('TS01017Q', 'ts01017q');
USERNAME
--------------------
TS01017Q
ts01017qつまり、引用符の有無は同じ名前の書き方の違いではなく、登録されるユーザーそのものが異なります。
先ほど引用符なしの接続が ORA-01017 になったのは、大文字小文字だけが違う「別のユーザー」に対して、その時点では存在しないままログインを試みていたためです。
ユーザーの一覧には見えているのに接続できない場合は、登録名が小文字(引用符付きで作成された名前)になっていないかを確認します。
3-7. OS 認証の失敗(/ as sysdba でも ORA-01017)
ここまではユーザー名とパスワードによる認証でしたが、ORA-01017 はパスワードを入力しない接続でも発生します。
データベースサーバー上で実行する sqlplus / as sysdba は、OS 認証という仕組みで接続します。
実行した OS ユーザーが OSDBA グループ(一般に dba という名前の OS グループ)に属していれば、ユーザー名もパスワードも確認されずに SYS として接続される方式です。
OSDBA グループに属さない OS ユーザー(検証では root)で実行すると、次のようになります。
# sqlplus / as sysdba
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
ユーザー名を入力してください:
(略・計3回失敗)
SP2-0157: 3回試行しましたがOracleに接続できませんでした。SQL*Plusを終了します。※出力は関連行のみ抜粋しています。SQL*Plus は接続に3回失敗すると SP2-0157 を出して終了します。
パスワードを1文字も入力していないのに、返ってくる番号と文言はこれまでの検証と同じ ORA-01017 です。
/ as sysdba が拒否されたときに疑うのは、データベースのユーザーやパスワードではなく、実行した OS ユーザーのグループです。
id コマンドで、OS ユーザーが dba グループに属しているかを確認します。
逆に、OSDBA グループに属する OS ユーザーであれば、/ as sysdba はユーザー名やパスワードの内容に関係なく接続に成功します。
この挙動と、SYSDBA まわりで発生する別のエラー(ORA-01031)については、別記事で取り上げます(次回公開)。
4. 資格情報が正しくても失敗する:ORA-01017 以外の番号で返るケース
ここまでの検証はすべて ORA-01017 でした。
一方、同じ「ログインできない」でも、原因によっては別の番号が返ります。
この章では、同じユーザー ts01017 の状態を1つずつ変えて、正しいユーザー名・正しいパスワードでも ORA-01017 にならないケースを再現します。
ALTER USER などの操作は SYSDBA のセッションで行い、接続テストのあとはそのつど SYSDBA に接続し直しています(CONNECT に失敗すると未接続になるため)。
この違いが重要なのは、別番号のエラーは「認証は通っている」ことを意味するためです。
番号を見た時点で、パスワードを疑う必要がないと分かります。
4-1. アカウントロック → ORA-28000
まず、アカウントをロックした状態です。
DBA が手動でロックする場合のほか、ログイン失敗の回数超過で自動的にロックされる場合もあります。
SQL> ALTER USER ts01017 ACCOUNT LOCK;
ユーザーが変更されました。DBA_USERS でアカウントの状態を確認すると、ACCOUNT_STATUS が LOCKED に変わり、LOCK_DATE にロックされた日時が記録されています。
SQL> SELECT username, account_status, lock_date FROM dba_users WHERE username = 'TS01017';
USERNAME ACCOUNT_STATUS LOCK_DATE
------------ -------------------- -------------------
TS01017 LOCKED 2026-08-16 15:56:17この状態で、正しいユーザー名・正しいパスワードで接続します。
SQL> CONNECT ts01017/"Ts01017#Lab"
ERROR:
ORA-28000: アカウントがロックされています。
警告: Oracleにはもう接続されていません。ORA-01017 ではなく ORA-28000 が返りました。
この番号が出た時点で、「パスワードは合っている・原因はロック」と切り分けられます。
資格情報をいくら見直しても解決せず、対処は DBA によるロック解除(ALTER USER ~ ACCOUNT UNLOCK)です。
4-2. パスワード期限切れ → ORA-28001
次に、パスワードの有効期限が切れた状態です。
SQL> ALTER USER ts01017 PASSWORD EXPIRE;
ユーザーが変更されました。
SQL> SELECT username, account_status, expiry_date FROM dba_users WHERE username = 'TS01017';
USERNAME ACCOUNT_STATUS EXPIRY_DATE
------------ -------------------- -------------------
TS01017 EXPIRED 2026-08-16 15:57:58正しい資格情報で接続します。
SQL> CONNECT ts01017/"Ts01017#Lab"
ERROR:
ORA-28001: パスワードが期限切れです。
ts01017に対するパスワードを変更しています。
新規パスワード:ここでも ORA-01017 ではなく、ORA-28001 が返りました。
パスワードそのものは正しく照合されており、期限が切れていることだけが問題です。
出力の後半にも注目してください。
SQL*Plus は ORA-28001 を検出すると、新しいパスワードへの変更を求める対話を自動的に開始します。
この対話は SQL*Plus の機能なので、アプリケーションからの接続では、変更を促す画面は出ずに ORA-28001 がエラーとしてアプリケーションに返ります。
「アプリだけログインできず、SQL*Plus で試すとパスワード変更を求められた」という状況は、この期限切れが原因です。
4-3. CREATE SESSION 権限なし → ORA-01045
最後に、認証は通るのに接続する権限がない状態です。
データベースへの接続には CREATE SESSION というシステム権限が必要で、これを取り消します。
SQL> REVOKE CREATE SESSION FROM ts01017;
取消しが成功しました。正しい資格情報で接続します。
SQL> CONNECT ts01017/"Ts01017#Lab"
ERROR:
ORA-01045: ユーザーTS01017にはCREATE
SESSION権限がありません。ログオンが拒否されました。
警告: Oracleにはもう接続されていません。※出力は端末の折り返しをそのまま載せています。
ORA-01045 が返りました。
このメッセージには、これまでとの決定的な違いがあります。
エラーが「ユーザーTS01017には」とユーザー名を名指しで返している点です。
ユーザーの存在すら示さない ORA-01017 に対し、ORA-01045 が名指しできるのは、認証(本人確認)がすでに成功しているためです。
ユーザー名もパスワードも正しく、足りないのは接続する権限だけ、と番号と文言から読み取れます。
4-4. 切り分け表
ここまでの結果を一覧にまとめます。
| エラー番号 | メッセージ(19c 実機) | 認証 | 原因 | 対処の方向 |
|---|---|---|---|---|
| ORA-01017 | ユーザー名/パスワードが無効です。ログオンは拒否されました。 | 失敗 | パスワード誤り・ユーザー不在・大文字小文字など(特定不可) | 資格情報側を順に確認 |
| ORA-28000 | アカウントがロックされています。 | 成功 | アカウントロック | DBA がロック解除 |
| ORA-28001 | パスワードが期限切れです。 | 成功 | パスワードの有効期限切れ | パスワード変更 |
| ORA-01045 | ユーザーXXにはCREATE SESSION権限がありません。ログオンが拒否されました。 | 成功 | 接続権限なし | DBA が CREATE SESSION を付与 |
ログイン失敗の調査は、この表の「どの行か」を確定するところから始まります。
ORA-28000・ORA-28001・ORA-01045 であれば、資格情報は正しいので、パスワードの再入力やユーザー名の見直しに時間を使う必要はありません。
5. 接続を試す前に dba_users で状態を読む
前の章の切り分けは、エラーが出た後の読み方でした。
DBA 権限があるなら、接続を試す前に対象ユーザーの状態を確認できます。
DBA_USERS を1回照会するだけで、前の章で再現した状態(ロック・期限切れ)と、ユーザーの存在そのものが確認できます。
SELECT username, account_status, lock_date, expiry_date, password_versions
FROM dba_users WHERE username = 'ユーザー名(大文字)';各列の見方は次のとおりです。
| 列 | 見るポイント |
|---|---|
| USERNAME | 行が返らなければユーザーが存在しない(登録名が小文字の可能性も含めて確認) |
| ACCOUNT_STATUS | OPEN=正常/LOCKED=ロック中(→ORA-28000)/EXPIRED=期限切れ(→ORA-28001) |
| LOCK_DATE | ロックされた日時 |
| EXPIRY_DATE | パスワードの有効期限 |
| PASSWORD_VERSIONS | パスワードの照合方式の世代(後述) |
正常な状態のユーザーは、次のように表示されます。
SQL> SELECT username, account_status, lock_date, expiry_date FROM dba_users WHERE username = 'TS01017';
USERNAME ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE
------------ -------------------- ------------------- -------------------
TS01017 OPEN 2027-02-12 15:40:48ここで注目したいのは、作成しただけのユーザーに EXPIRY_DATE(有効期限)が自動で付いている点です。
本検証環境では、ユーザー作成日の約180日後が設定されていました。
デフォルトのプロファイルの PASSWORD_LIFE_TIME(デフォルト値は180日)によるもので、期限を過ぎると前の章で再現した ORA-28001 になります。
「何も設定した覚えがないのに期限切れになった」の正体はこの自動設定です。
最後の PASSWORD_VERSIONS 列は、古いクライアントからの接続だけが ORA-01017 になるケースに関係します。
SQL> SELECT username, password_versions FROM dba_users WHERE username = 'TS01017';
USERNAME PASSWORD_VERSIONS
------------ --------------------
TS01017 11G 12Cこの列は、そのユーザーのパスワードがどの世代の照合方式で保存されているかを示します(世代が作られるのは、ユーザーの作成時とパスワードの変更時です)。
19c のデフォルト設定で作成したユーザーは 11G と 12C の両方を持ちますが、サーバー側の設定(sqlnet.ora の SQLNET.ALLOWED_LOGON_VERSION_SERVER)を厳しくすると、古い世代が作られなくなります。
接続するクライアントが対応する世代がこの列にないと、正しいパスワードでも ORA-01017 で拒否されます。
「新しい環境に移行したら、古いアプリケーションサーバーからだけ接続できなくなった」という形で表面化するため、特定のクライアントだけが失敗する場合はこの列と sqlnet.ora の設定を確認します。
なお、クライアントの認証プロトコル自体がサーバーの要求より古い場合は、ORA-01017 ではなく ORA-28040(一致する認証プロトコルがありません)が返ります。
ここでも、番号がどちらかで確認すべき場所が変わります。
この再現には古いクライアント環境が必要なため、本記事では確認ポイントの提示に留めています。
6. よくある Q&A
Q1. パスワードは絶対に合っているのに ORA-01017 が出ます。他に何を疑えばよいですか?
本人が気づきにくい原因が残っています。
次の順に確認します。
- パスワードの大文字小文字(Caps Lock・コピー時の変換)
- ユーザー名の思い込み(別のユーザー名との混同・接続先データベースの取り違え)
- 登録名が小文字のユーザー(引用符付きで作成されたユーザーに引用符なしで接続していないか)
- 特定のクライアントからだけ失敗する場合は、PASSWORD_VERSIONS とサーバー側の設定
DBA 権限があれば、「接続を試す前に dba_users で状態を読む」の章のとおり、ユーザーの存在と登録名を DBA_USERS で直接確認するのが確実です。
Q2. ユーザー名とパスワードのどちらを間違えたのか、確認する方法はありませんか?
エラー出力からは確認できません。
本記事の検証のとおり、パスワード誤りと存在しないユーザーの出力は一字一句同じで、アカウントの存在が外部に分からないようになっています。
切り分けたい場合は、DBA 権限で DBA_USERS を照会し、ユーザーの存在と状態を直接確認します。
ユーザーが実在して ACCOUNT_STATUS が OPEN であれば、残る原因はパスワード側(誤り・大文字小文字)に絞られます。
Q3. パスワードを何回も間違えると、アカウントはどうなりますか?
一定回数を超えると、アカウントが自動的にロックされます。
上限はプロファイルの FAILED_LOGIN_ATTEMPTS で決まり、デフォルトのプロファイルでは10回です。
ロック後は、正しいパスワードでも ORA-28000 が返ります。
ロックの継続期間もプロファイルで決まり(PASSWORD_LOCK_TIME)、デフォルトでは1日が経過すると自動的に解除されます。
エラー番号が ORA-01017 から ORA-28000 に変わったら、試行の繰り返しをやめて、DBA にロック解除を依頼するか自動解除を待ちます。
ロックの仕組みと運用は、ORA-28000 を主題にした別記事で取り上げます(次回公開)。
Q4. 本番環境で ORA-01017 が報告されたとき、DBA はまず何を確認すればよいですか?
接続の再試行より先に、DBA_USERS の1回の照会で対象ユーザーの状態を確認します。
SELECT username, account_status, lock_date, expiry_date, password_versions
FROM dba_users WHERE username = 'ユーザー名(大文字)';行が返らなければユーザー名側、LOCKED / EXPIRED ならそもそも ORA-01017 ではなく ORA-28000 / ORA-28001 の問題です。
状態が OPEN でユーザーも実在するなら、パスワード側(誤り・大文字小文字・パスワードバージョン)に調査を絞ります。
Q5. ORA-28002 というよく似た番号を見たことがあります。ORA-28001 とは何が違いますか?
ORA-28002 は「パスワードが期限切れ間近」の警告で、猶予期間(プロファイルの PASSWORD_GRACE_TIME で決まる期間。デフォルトは7日)の間に表示されます。
この段階ではまだログインできます。
一方、ORA-28001 は猶予期間も終了した後の拒否で、ログインできません。
この2段階の流れは、『Oracle Databaseセキュリティ・ガイド』の「パスワード変更のライフ・サイクル」の節で説明されています。
ORA-28002 が出始めた時点でパスワードを変更しておけば、ORA-28001 による業務停止を防げます。
Q6. サーバー上の sqlplus / as sysdba が ORA-01017 になります。パスワードを設定し直すべきですか?
パスワードの問題ではありません。
/ as sysdba は OS 認証で接続するため、確認されるのは実行した OS ユーザーが OSDBA グループ(一般に dba グループ)に属しているかどうかだけです。
まず id コマンドで、実行した OS ユーザーの所属グループを確認します。
本記事の検証でも、グループに属さない OS ユーザーからの実行は、パスワードを入力していないのに ORA-01017 になりました。
対処は、oracle ユーザーなど OSDBA グループに属する OS ユーザーに切り替えて(su - oracle)実行し直すのが基本です。
OS ユーザーを dba グループに追加する方法もありますが、資格情報が一切確認されないことは本記事の検証のとおりで、追加はパスワードなしで SYS として接続できる権限を渡すことと同じです。
グループ追加の手順を含む OS 認証まわりの詳細は、別記事で取り上げます(次回公開)。
Q7. この記事の CONNECT はパスワードを二重引用符で囲んでいますが、囲まないと接続できないのですか?
囲まなくても接続できる場合が多いですが、記号入りのパスワードでは常に囲むのが確実です。
囲むことが必須なのは、「正しい資格情報でログインできる状態を作る」の節で述べたとおり、パスワードがアルファベット以外の文字で始まるか、英数字と _ $ # 以外の文字を含む場合です。
本記事のパスワード Ts01017#Lab は記号が # だけなので、この必須条件に該当しません。
実際に、別の検証ユーザー ts01017p を引用符なしで作成し、囲み方を変えて接続した結果が次のとおりです。
SQL> CREATE USER ts01017p IDENTIFIED BY Ts01017#Lab;
ユーザーが作成されました。
SQL> GRANT CREATE SESSION TO ts01017p;
権限付与が成功しました。
SQL> CONNECT ts01017p/"Ts01017#Lab"
接続されました。
SQL> CONNECT ts01017p/"TS01017#LAB"
ERROR:
ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
警告: Oracleにはもう接続されていません。
SQL> CONNECT ts01017p/Ts01017#Lab
接続されました。この結果から、次の3点が確認できます。
- 引用符なしの CREATE USER も、引用符なしの CONNECT も、そのまま成功する(
#は囲まなくてよい文字) - 引用符なしで作成したパスワードに、二重引用符で囲んで接続できる。つまり、二重引用符は区切りの記号で、パスワードの文字として保存されていない
- 大文字に変えた “TS01017#LAB” は ORA-01017 になる。引用符なしで作成しても、パスワードの大文字小文字は入力どおりに保存される(引用符なしだと大文字化されるユーザー名とは別の挙動)
逆に、囲むことが必須のパスワードを囲まずに指定すると、CREATE USER 自体がエラーになります。
実機では、先頭が数字のパスワードと @ を含むパスワードは ORA-00922(オプション指定されていないか、または無効です)、先頭が # のパスワードは ORA-00911(文字が無効です)で拒否されました。
どれも SQL の書き方の段階で止まる構文エラーで、認証までは進みません。
意図しないパスワードのままユーザーが作られてしまう心配はない一方、メッセージからはパスワードの書き方が原因だと気づきにくい番号が返る点に注意が必要です。
特に @ は、引用符が必須になる記号であるうえ、SQL*Plus の接続の書き方(ユーザー名/パスワード@接続先)とも紛らわしい文字です。
記号入りのパスワードは、常に囲んでおくと安全です。
7. まとめ
ORA-01017 の切り分けの型を整理します。
- ORA-01017 は原因を1つに絞れない。 単純な誤り(パスワード誤り・ユーザー不在)も、気づきにくい原因(大文字小文字・引用符付きユーザー・OS 認証失敗)も、すべて同じ出力になる(アカウントの存在を外部に示さない動作)
- まず番号を確認する。 ORA-28000(ロック)・ORA-28001(期限切れ)・ORA-01045(権限なし)なら認証は通っており、パスワードを疑う必要はない
- DBA は接続を試す前に DBA_USERS を照会する。 存在・ACCOUNT_STATUS・LOCK_DATE・EXPIRY_DATE・PASSWORD_VERSIONS の1回の照会で当たりを付けられる
- パスワードはデフォルトで大文字小文字が区別される。 ユーザー名は引用符なしなら大文字に変換され、引用符付きで作成すると小文字のまま登録される
調査の流れをフローにすると次のとおりです。
ログインに失敗したら、まずエラー番号を確認
│
├─ ORA-28000 → アカウントロック(パスワードは合っている)
├─ ORA-28001 → パスワード期限切れ(パスワードは合っている)
├─ ORA-01045 → CREATE SESSION 権限なし(認証は通っている)
├─ ORA-28040 → クライアントの認証プロトコルが古い(資格情報以前の問題)
│
└─ ORA-01017 → 原因は1つに絞れない
├─ DBA権限あり → dba_users で存在・状態・登録名を確認
├─ パスワードの誤り・大文字小文字を確認
├─ ユーザー名の誤り・引用符付き作成(小文字登録)を確認
├─ / as sysdba の失敗 → OS ユーザーのグループを id で確認
└─ 特定クライアントだけ失敗 → PASSWORD_VERSIONS を確認同じ ORA-01017 でも、エラー番号と DBA_USERS の状態を先に読めば、再試行を繰り返す前に原因の見当を付けられます。
繰り返しの試行は FAILED_LOGIN_ATTEMPTS の超過によるロックを招くため、切り分けの順番そのものがロックという二次被害の防止にもなります。








