-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[후_Hwi] 웹서버 4단계 - 쿠키를 이용한 로그인 구현 #75
base: hooi
Are you sure you want to change the base?
Changes from all commits
3779d10
e842a16
6fc824d
1066e1d
fea114e
222e9cb
32b0449
ec902b8
0a031a4
369a91d
f634483
a80263a
2eeaf38
836ff04
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package controller; | ||
|
||
import http.Request; | ||
import http.Response; | ||
|
||
import java.io.IOException; | ||
|
||
public interface Controller { | ||
public Response run(Request request) throws IOException; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package controller; | ||
|
||
import http.Request; | ||
import http.Response; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class DefaultController implements Controller { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(DefaultController.class); | ||
private static final DefaultController instance = new DefaultController(); | ||
|
||
public static DefaultController getInstance() { | ||
return instance; | ||
} | ||
|
||
private DefaultController() { | ||
|
||
} | ||
|
||
@Override | ||
public Response run(Request request) throws IOException { | ||
String url = request.methodUrl().getValue(); // /index.html | ||
String contentType = url.split("\\.")[1]; | ||
byte[] body = Files.readAllBytes(new File("./webapp" + url).toPath()); | ||
Map<String, String> responseHeader = new HashMap<>(); | ||
// responseHeader.put("Content-Type", "text/" + contentType + ";charset=utf-8"); | ||
responseHeader.put("Content-Length", String.valueOf(body.length)); | ||
Response response = new Response("HTTP/1.1", "200", "OK", responseHeader, body); | ||
log.debug("[response] : {}", response.responseMessage()); | ||
return response; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package controller; | ||
|
||
import db.DataBase; | ||
import http.Request; | ||
import http.Response; | ||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
|
||
public class LogInController implements Controller { | ||
private static final Logger log = LoggerFactory.getLogger(LogInController.class); | ||
private static final LogInController instance = new LogInController(); | ||
|
||
public static LogInController getInstance() { | ||
return instance; | ||
} | ||
|
||
private LogInController() { | ||
|
||
} | ||
|
||
@Override | ||
public Response run(Request request) { | ||
String userId = request.findBodyByFieldName("userId"); | ||
String password = request.findBodyByFieldName("password"); | ||
Optional<User> user = DataBase.findUserById(userId); | ||
|
||
Map<String, String> responseHeader = new HashMap<>(); | ||
responseHeader.put("Content-Type", "text/html;charset=utf-8"); | ||
responseHeader.put("Content-Length", String.valueOf(0)); | ||
if (user.isEmpty() || !user.get().isCorrectPassword(password)) { | ||
log.debug("로그인을 실패하였습니다!"); | ||
responseHeader.put("Location", "/user/login_failed.html"); | ||
|
||
} else if (user.get().isCorrectPassword(password)) { | ||
log.debug("로그인을 성공했습니다!"); | ||
responseHeader.put("Location", "/index.html"); | ||
responseHeader.put("Set-Cookie", "logined=true; Path=/"); | ||
} | ||
Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, "".getBytes()); | ||
log.debug("[response] : {}", response.responseMessage()); | ||
return response; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package controller; | ||
|
||
import http.Request; | ||
import http.Response; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class LogOutController implements Controller { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(LogOutController.class); | ||
private static final LogOutController instance = new LogOutController(); | ||
|
||
public static LogOutController getInstance() { | ||
return instance; | ||
} | ||
|
||
private LogOutController() { | ||
|
||
} | ||
|
||
@Override | ||
public Response run(Request request) throws IOException { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 뭔가 로그아웃을 위한 로직은 없는 것 같습니다? |
||
byte[] body; | ||
body = Files.readAllBytes(new File("./webapp" + "/index.html").toPath()); | ||
Map<String, String> responseHeader = new HashMap<>(); | ||
responseHeader.put("Content-Type", "text/html;charset=utf-8"); | ||
responseHeader.put("Content-Length", String.valueOf(body.length)); | ||
responseHeader.put("Location", "/index.html"); | ||
responseHeader.put("Set-Cookie", "logined=true; Max-Age=0; Path=/"); | ||
Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, body); | ||
log.debug("[response] : {}", response.responseMessage()); | ||
return response; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package controller; | ||
|
||
import db.DataBase; | ||
import http.Request; | ||
import http.Response; | ||
import model.User; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.function.Consumer; | ||
|
||
public class SignUpController implements Controller { | ||
|
||
private static final Logger log = LoggerFactory.getLogger(SignUpController.class); | ||
private static final SignUpController instance = new SignUpController(); | ||
|
||
public static SignUpController getInstance() { | ||
return instance; | ||
} | ||
|
||
private SignUpController() { | ||
|
||
} | ||
|
||
@Override | ||
public Response run(Request request) { | ||
byte[] body = "".getBytes(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 어떤 의미인지요? |
||
Map<String, String> responseHeader = new HashMap<>(); | ||
responseHeader.put("Content-Type", "text/html;charset=utf-8"); | ||
responseHeader.put("Content-Length", String.valueOf(body.length)); | ||
|
||
DataBase.findUserById(request.findBodyByFieldName("userId")) | ||
.ifPresentOrElse( | ||
redirectSignUpFail(responseHeader), | ||
redirectSignUpSuccess(request, responseHeader) | ||
); | ||
Response response = new Response("HTTP/1.1", "302", "Found", responseHeader, body); | ||
log.debug("[response] : {}", response.responseMessage()); | ||
return response; | ||
} | ||
|
||
private Runnable redirectSignUpSuccess(Request request, Map<String, String> responseHeader) { | ||
return () -> { | ||
createUser(request); | ||
responseHeader.put("Location", "/index.html"); | ||
}; | ||
} | ||
Comment on lines
+44
to
+49
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
private void createUser(Request request) { | ||
User user = new User( | ||
request.findBodyByFieldName("userId"), | ||
request.findBodyByFieldName("password"), | ||
request.findBodyByFieldName("name"), | ||
request.findBodyByFieldName("email")); | ||
log.debug("User : {}", user); | ||
DataBase.addUser(user); | ||
} | ||
|
||
private Consumer<User> redirectSignUpFail(Map<String, String> responseHeader) { | ||
return user -> { | ||
responseHeader.put("Location", "/user/form.html"); | ||
log.debug("중복된 아이디가 존재합니다."); | ||
}; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package http; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import util.HttpRequestUtils; | ||
import util.IOUtils; | ||
import util.Pair; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.InputStreamReader; | ||
import java.net.URLDecoder; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
public class Request { | ||
private static final Logger log = LoggerFactory.getLogger(Request.class); | ||
|
||
private final int METHOD = 0; | ||
private final int URL = 1; | ||
private final int HTTP_VERSION = 2; | ||
private final int KEY = 0; | ||
private final int VALUE = 1; | ||
|
||
private String httpMethod; | ||
private String requestUrl; | ||
private String httpVersion; | ||
private Map<String, String> requestHeaderField = new HashMap<>(); | ||
private Map<String, String> requestBody = new HashMap<>(); | ||
|
||
public Request(InputStream in) throws IOException { | ||
BufferedReader input = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); | ||
setRequestLine(input); | ||
setRequestHeader(input); | ||
setRequestBody(input); | ||
} | ||
|
||
private void setRequestLine(BufferedReader input) throws IOException { | ||
String requestLine = URLDecoder.decode(input.readLine(), StandardCharsets.UTF_8); | ||
log.debug("<<<<<request start>>>>>"); | ||
log.debug("[request line] : {}", requestLine); | ||
|
||
String[] requestInfo = HttpRequestUtils.getRequestInfo(requestLine); | ||
httpMethod = requestInfo[METHOD]; | ||
requestUrl = requestInfo[URL]; | ||
httpVersion = requestInfo[HTTP_VERSION]; | ||
Comment on lines
+46
to
+48
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 굉장히 굉장히 사이드 이펙이 발생하기 쉬운 구조로 보이고요... 그러니까 |
||
} | ||
|
||
private void setRequestHeader(BufferedReader input) throws IOException { | ||
String line; | ||
while (!"".equals(line = URLDecoder.decode(input.readLine(), StandardCharsets.UTF_8))) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (line == null) { | ||
return; | ||
} | ||
Pair pair = HttpRequestUtils.parseHeader(line); | ||
requestHeaderField.put(pair.getKey(), pair.getValue()); | ||
} | ||
|
||
requestHeaderField.entrySet().forEach(e -> { | ||
log.debug("{} : {}", e.getKey(), e.getValue()); | ||
}); | ||
log.debug("<<<<<request end>>>>>"); | ||
} | ||
|
||
private void setRequestBody(BufferedReader input) throws IOException { | ||
int contentLength = (requestHeaderField.get("Content-Length") == null) ? | ||
0 : Integer.parseInt(requestHeaderField.get("Content-Length")); | ||
String data = IOUtils.readData(input, contentLength); | ||
String decodedData = URLDecoder.decode(data, StandardCharsets.UTF_8); | ||
requestBody = HttpRequestUtils.parseRequestBody(decodedData); | ||
} | ||
|
||
public Pair methodUrl() { | ||
return new Pair(httpMethod, requestUrl); | ||
} | ||
|
||
public String findBodyByFieldName(String fieldName) { | ||
return requestBody.get(fieldName); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래쪽 로직을 보니
.get()
을 호출하고 있던데 옵셔널 객체를 강제 언래핑하는 것은 피해 주시고요.User
가 이 로직 안에서Optional
상태로 존재할 이유가 있나요? 저라면 여기서.orElseThrow()
와 같은 편의 메소드를 사용할 것 같아요.