학습 목표
-로그인 기능 구현을 통한 쿠키와 세션에 대한 대략적인 이해
-로그인 사용자에 대한 접근 제한
학습 목차
3-1. 로그인 기능 구현
3-2. 로그인 상태에 따른 메뉴 처리 및 로그아웃
3-3. 로그인 사용자에 한해 자신의 정보를 수정하도록 수정
3-4. 중복 제거 및 읽기 좋은 코드를 위한 리팩토링
3-5. 질문하기, 질문목록 기능 구현
3-6. 원격 서버에 소스 코드 배포
//UserController.java
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/loginForm") //1.
public String loginForm() {
return "/user/login";
}
@PostMapping("/login") //2.
public String login(String userId, String password, HttpSession session) { //6.
User user=userRepository.findByUserId(userId); //3.
if(user==null) { //4.
System.out.println("Login Failure!"); 7.
return "redirect:/users/loginForm";
}
if(!password.equals(user.getPassword()) { //5.
System.out.println("Login Failure!"); //7.
return "redirect:/users/loginForm";
}
System.out.println("Login Success!"); //7.
session.setAttribute("user", user); //6.
return "redirect:/";
}
@GetMapping("/form")
public String form() {
return "/user/form";
}
@PostMapping("")
public String create(User user) {
System.out.println("user : " + user);
userRepository.save(user);
return "redirect:/users";
}
@GetMapping("")
public String list(Model model) {
model.addAttribute("users", userRepository.findAll());
return "/user/list";
}
@GetMapping("/{id}/form")
public String updateForm(@PathVariable Long id, Model model) {
model.addAttribute("user", userRepository.findById(id).get())
return "/user/updateForm";
}
@PutMapping("/{id}")
public String update(@PathVariable Long id, User newUser) {
User user=userRepository.findById(id).get();
user.update(newUser);
userRepository.save(user);
return "redirect:/users";
}
}
1. 로그인 form에서 로그인 정보를 입력받습니다.
2. 로그인을 하면 그 정보를 전달 받고, 메인 페이지로 이동하도록 합니다.
3. primary key는 id로 설정되어 있는데, userId를 통해 조회를 하고싶은 경우, UserRepository클래스에 findByUserId를 만들어주어야 합니다.
4. user 정보가 존재하지 않으면, 로그인 페이지로 이동하도록 합니다.
5. password가 일치하지 않으면, 로그인 페이지로 이동하도록 합니다.
6. 로그인이 잘 되었으면, 로그인 정보를 세션에 저장합니다.
7. 기능이 제대로 작동하는지 확인하기 위해 콘솔에 log를 출력합니다.
//UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
User findByUserId(String userId); //1.
}
1. findBy조회하고싶은속성이름(인자): userId를 기반으로 데이터를 조회할 수 있습니다.
<!--login.html-->
<form name="question" method="post" action="/users/login"> <!--1.-->
<div class="form-group">
<label for="userId">사용자 아이디</label>
<input class="form-control" id="userId" name="userId" placeholder="User Id">
</div>
<div class="form-group">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password" placeholder="Password">
</div>
</form>
1. action의 주소를 "/users/login"으로 변경합니다.
//User.java
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
@Column(nullable=false, length=20)
private String userId;
private String password;
private String name;
private String email;
public void setUserId(String userId) {
this.userId=userId;
}
public void setPassword(String password) {
this.password=password;
}
public String getPassword() { //1.
return password;
}
public void setName(String name) {
this.name=name;
}
public void setEmail(String email) {
this.email=email;
}
public void update(User newUser) {
this.password=newUser.password;
this.name=newUser.name;
this.email=newUser.email;
}
@Override
public String toString() {
return "User [userId=" + userId + ", password=" + password + ", name=" + name, "email=" + email +"]";
}
}
1. getPassword 메소드를 추가합니다.
//import.sql
INSERT INTO USER (USER_ID, PASSWORD, NAME, EMAIL) VALUES ('may', 'test', '메이', 'may@slipp.net');
INSERT INTO USER (USER_ID, PASSWORD, NAME, EMAIL) VALUES ('april', 'test', '에이프릴', 'april@slipp.net');
<!--navigation.html-->
<meta charset="utf-8">
<!--한글 깨짐 해결하기 위해 추가해줌-->
<nav class="navbar navbar-fixed-top header">
<div class="col-md-12">
<div class="navbar-header">
<a href="/" class="navbar-brand">SLiPP</a>
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#navbar-collapse1">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse1">
<form class="navbar-form pull-left">
<div class="input-group" style="max-width: 470px;">
<input type="text" class="form-control" placeholder="Search"
name="srch-term" id="srch-term">
<div class="input-group-btn">
<button class="btn btn-default btn-primary" type="submit">
<i class="glyphicon glyphicon-search"></i>
</button>
</div>
</div>
</form>
<ul class="nav navbar-nav navbar-right">
<li><a href="#" class="dropdown-toggle" data-toggle="dropdown"><i
class="glyphicon glyphicon-bell"></i></a>
<ul class="dropdown-menu">
<li><a href="https://slipp.net" target="_blank">SLiPP</a></li>
<li><a href="https://facebook.com" target="_blank">Facebook</a></li>
</ul></li>
<li><a href="/users"><i class="glyphicon glyphicon-user"></i></a></li>
</ul>
</div>
</div>
</nav>
<div class="navbar navbar-default" id="subnav">
<div class="col-md-12">
<div class="navbar-header">
<a href="#" style="margin-left: 15px;"
class="navbar-btn btn btn-default btn-plus dropdown-toggle"
data-toggle="dropdown"><i class="glyphicon glyphicon-home"
style="color: #dd1111;"></i> Home <small><i
class="glyphicon glyphicon-chevron-down"></i></small></a>
<ul class="nav dropdown-menu">
<li><a href="../user/profile.html"><i
class="glyphicon glyphicon-user" style="color: #1111dd;"></i>
Profile</a></li>
<li class="nav-divider"></li>
<li><a href="#"><i class="glyphicon glyphicon-cog"
style="color: #dd1111;"></i> Settings</a></li>
</ul>
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#navbar-collapse2">
<span class="sr-only">Toggle navigation</span> <span
class="icon-bar"></span> <span class="icon-bar"></span> <span
class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="navbar-collapse2">
<ul class="nav navbar-nav navbar-right">
<li class="active"><a href="/">Posts</a></li>
{{^sessionedUser}} <!--1.-->
<li><a href="/users/login" role="button">로그인</a></li>
<li><a href="/users/form" role="button">회원가입</a></li>
{{/sessionedUser}}
{{#sessionedUser}} <!--1.-->
<li><a href="/users/logout" role="button">로그아웃</a></li> <!--2.-->
<li><a href="/users/{{id}}/form" role="button">개인정보수정</a></li>
{{/sessionedUser}}
</ul>
</div>
</div>
</div>
1. {{^user}}: user 정보가 없을 때
{{#user}}: user 정보가 있을 때
두 가지를 if else문 처럼 사용할 수 있습니다.
sessionedUser: 세션에 있는 user의 정보를 가져옵니다.
2. "/users/logout": users 파일 아래에 logout 파일을 만듭니다.
//UserController.java
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/loginForm")
public String loginForm() {
return "/sessionedUser/login"; //2.
}
@PostMapping("/login")
public String login(String userId, String password, HttpSession session) {
User user=userRepository.findByUserId(userId);
if(user==null) {
System.out.println("Login Failure!");
return "redirect:/users/loginForm";
}
if(!password.equals(user.getPassword()) {
System.out.println("Login Failure!");
return "redirect:/users/loginForm";
}
System.out.println("Login Success!");
session.setAttribute("sessionedUser", user); //2.
return "redirect:/";
}
@GetMapping("/logout") //1.
public String logout(HttpSession session) {
session.removeAttribute("sessionedUser");
return "redirect:/";
}
@GetMapping("/form")
public String form() {
return "/user/form";
}
@PostMapping("")
public String create(User user) {
System.out.println("user : " + user);
userRepository.save(user);
return "redirect:/users";
}
@GetMapping("")
public String list(Model model) {
model.addAttribute("users", userRepository.findAll());
return "/user/list";
}
@GetMapping("/{id}/form")
public String updateForm(@PathVariable Long id, Model model, HttpSession session) {
Object tempUser=session.getAtrribute("sessionedUser"); //3.
if(tempUser==null) { //4.
return "redirect:/users/loginForm";
}
User sessionedUser=(User)tempUser;
if(!id.equals(sessionedUser.getId()){ //5.
throw new IllegalStateException("You can't update the another user");
}
User user=userRepository.findById(id).get();
model.addAttribute("user", userRepository.findById(id).get())
return "/user/updateForm";
}
@PutMapping("/{id}")
public String update(@PathVariable Long id, User updatedUser, HttpSession session) {
Object tempUser=session.getAtrribute("sessionedUser"); //3.
if(tempUser==null) { //4.
return "redirect:/users/loginForm";
}
User sessionedUser=(User)tempUser;
if(!id.equals(sessionedUser.getId()){ //5.
throw new IllegalStateException("You can't update the another user");
}
User user=userRepository.findById(id).get();
user.update(updatedUser);
userRepository.save(user);
return "redirect:/users";
}
}
1. 로그인을 하게 되면 세션에 사용자 정보가 저장됩니다.
로그아웃을 할 때는 세션에 저장된 정보를 삭제해주면 됩니다.
2. "user"라는 이름을 다른 곳에서 사용하고 있으므로 중복되지 않게 "sessionedUser"로 바꿔줍니다.
user: 모델에 담긴 사용자 정보
sessionedUser: 로그인, 로그아웃 할 때 사용자 정보
3. 현재의 sessionedUser정보(로그인 정보)를 저장합니다.
4. tempUser 값이 널이면, 로그인 페이지로 이동합니다.
5. 자신의 정보와 일치하지 않으면 정보를 수정할 수 없도록 합니다.
1) if(!id.equals(sessionedUser.getId()) {
throw new IllegalStateException("");
}
Useruser=userRepository.findById(id).get();
2) User user=userRepository.findById(sessionedUser.getId()).get();
두 가지 방식 중 하나를 사용할 수 있습니다.
'Spring > 게시판 만들기 프로젝트' 카테고리의 다른 글
[Spring Boot] #4_1 게시판 만들기 (0) | 2020.12.22 |
---|---|
[Spring Boot] #3_2 게시판 만들기 (0) | 2020.12.21 |
[Spring Boot] #2_2 게시판 만들기 (0) | 2020.12.09 |
[Spring Boot] #2_1 게시판 만들기 (0) | 2020.12.09 |
[Spring Boot] #1 게시판 만들기 (0) | 2020.12.07 |