-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUser.java
255 lines (212 loc) · 6.22 KB
/
User.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
//memo:UserはUsersの内部クラスにするのはどうなんだろうか
/*
* 1:ClientがUserを持つ
* 2:UserはUsersで管理
* 3:Usersを持つのはServer
* 4:ClientはServerのUsersを通してUserを作成&取得(認証)
* 5:Usersはデータベースとやりとりする
*/
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.security.*;
public class User{
private String name = null;
private String password = null;
//Clientから呼び出す ここでバリデイトしてClientでtrueが返ってくるまで繰り返し呼び出せばよい
//修正1:Clientではなくユーザを管理するUsersでユーザの追加、削除、認証を行う
boolean setName(String name){
this.name = name;
return true;
}
boolean setPassword(String password){
this.password = password;
return true;
}
String getName(){
return this.name;
}
String getPassword(){
return this.password;
}
}
class Users{
private List<User> users = new ArrayList<User>();
//ユーザで使う入出力
private BufferedReader in;
private PrintWriter out;
private String filename = "users.dat";
//users作成時にユーザで使う入出力を渡す
public Users(BufferedReader in, PrintWriter out){
this.in = in;
this.out = out;
}
// ファイルから既存のユーザデータを読み込む
public boolean readUserData(){
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
String line;
while ((line = br.readLine()) != null) {
String text[] = line.split(",", 2);
User user = new User();
user.setName(text[0]);
user.setPassword(text[1]);
users.add(user);
}
br.close();
} catch(Exception e) {
System.err.println(e);
}
return true;
}
// ユーザ認証 (名前を返す)
public String authenticate() {
out.println("=========================");
out.println("■ ログインします。ログイン情報を入力してください。");
out.println("=========================");
out.flush();
try {
out.print("name : ");
out.flush();
String name = in.readLine();
out.print("password : ");
out.flush();
String password = hash(in.readLine());
for(User user : users){
if(user.getName().equals(name)){
if(user.getPassword().equals(password)){
out.println("ユーザ認証に成功しました");
out.flush();
return name;
}else{
out.println("パスワードが間違っています");
out.flush();
return "";
}
}
}
out.println("ユーザ名が間違っています");
out.flush();
return "";
} catch(IOException e) {
e.printStackTrace();
return "";
}
}
//超簡易ユーザ認証(User)
//引数passwordは、ハッシュ化済みのものが渡されることを想定している
public User getUser(String name, String password){
for(User user : users){
if(user.getName().equals(name)){
if(user.getPassword().equals(password)){
return user;
}else{
return null;
}
}
}
return null;
}
public boolean createUser(){
User user = new User();
out.println("=========================");
out.println("■ アカウントを作成します。");
out.println("=========================");
out.flush();
try{
String name, password;
boolean flag1 = false, flag2 = true;
//ユーザ名が半角英数+下線のみで構成されているか調べるための正規表現
Pattern p = Pattern.compile("^[a-zA-Z0-9_]+$");
//nameを登録
while(true){
out.print("name : ");
out.flush();
name = in.readLine();
flag1 = p.matcher(name).find();
for(User u : users)
if(u.getName().equals(name)) flag2 = false;
if(!flag1) {
out.println("ユーザ名に使えるのは、半角英数字と下線のみです。");
out.flush();
} else if(!flag2) {
out.println("そのユーザ名は既に使われています。");
out.flush();
} else {
if(user.setName(name)) break;
}
}
//passwordを登録
//パスワードはどうせハッシュ化するので、どんな文字を使っても可
while(true){
out.print("password : ");
out.flush();
password = hash(in.readLine());
if(user.setPassword(password)) break;
}
//userを追加
users.add(user);
//ユーザ情報を格納するファイルにも追加
PrintWriter pw = new PrintWriter(new FileWriter(filename, true));
pw.println(name + "," + password);
pw.close();
}catch(IOException error){
error.printStackTrace();
}
return true;
}
public boolean deleteUser(){
out.println("=========================");
out.println("■ アカウントを削除します。");
out.println("=========================");
out.flush();
try{
out.print("Name : ");
out.flush();
String name = in.readLine();
out.print("password : ");
out.flush();
String password = hash(in.readLine());
User user = this.getUser(name, password);
if(user!=null){
this.users.remove(user);
(new File(filename)).delete();
PrintWriter pw = new PrintWriter(new FileWriter(filename, true));
for(User u : users)
pw.println(u.getName() + "," + u.getPassword());
pw.close();
out.println("ユーザを消去しました");
out.flush();
}else{
out.println("ユーザ認証に失敗しました");
out.flush();
}
}catch(IOException error){
error.printStackTrace();
}
return true;
}
// パスワードをハッシュ化する関数
public String hash(String password){
String digest = "";
try {
MessageDigest md = MessageDigest.getInstance("SHA-512");
md.update(password.getBytes());
byte[] hash = md.digest();
StringBuilder sb = new StringBuilder();
for(byte b : hash) sb.append(String.format("%02x", b));
digest = sb.toString();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return digest;
}
public static void main(String[] args) throws ClassNotFoundException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
Users users = new Users(in, out);
users.readUserData();
users.authenticate();
users.deleteUser();
}
}