Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Spring Boot
- JDBC
- 김영한
- Servlet
- Proxy
- db
- springdatajpa
- java
- 스프링 핵심 기능
- spring
- jpa
- JPQL
- 인프런
- Thymeleaf
- 자바
- AOP
- kotlin
- 알고리즘
- Exception
- http
- pointcut
- 백준
- transaction
- Android
- 스프링 핵심 원리
- Greedy
- QueryDSL
- 스프링
- SpringBoot
- 그리디
Archives
- Today
- Total
개발자되기 프로젝트
관리자 권한 본문
1. 관리자 권한
- 관리자는 모든 권한을 가지고 있다.
- 모든 글/댓글에 대한 수정&삭제 권한이 있음.
2. 권한 level 설정
- 본격적인 코드 작성에 앞서서 권한의 level을 다음과 같이 수직적(?)으로 수정했다.
- admin : 모든 글/댓글에 대한 수정/삭제 권한
- normal : 본인이 작성한 글에 대해 수정/삭제 권한. 본인이 작성한 댓글에 대한 삭제 권한
- commentOnly : 해당 글에 대해 댓글만 작성 가능. 본인이 작성한 댓글에 대한 삭제 권한.
- guest : 조회만 가능. 수정/삭제에 대한 모든 권한 없음.
public interface Authority {
String admin = "admin"; //모든 권한
String normal = "normal"; //해당 글 + 본인 댓글에 대한 권한
String commentOnly = "commentOnly"; //댓글 작성, 본인 댓글만 수정 가능.
String guest = "guest"; //모든 권한 없음.
}
3. LoginController
- admin계정이 로그인 하는 경우 authority에 admin을 지정.
@PostMapping("/login")
public String login(@Validated @ModelAttribute("loginForm") LoginForm form, Model model,
BindingResult bindingResult, HttpServletResponse response){
if(bindingResult.hasErrors()){
return "login/loginForm";
}
MemberDto loginMember = loginService.login(form.getLoginId(), form.getPassword());
if(loginMember == null){
bindingResult.reject("loginFail", "id또는 pw정보가 맞지 않습니다.");
return "login/loginForm";
}
//로그인 성공
//관리자 확인
if(form.getLoginId().equals("admin")){
loginMember.setAuthority(Authority.admin);
}
model.addAttribute("member", loginMember);
//세션으로 쿠키 처리.
sessionManager.createSession(loginMember, response);
return "redirect:/";
}
4. PostController
- 글 목록 조회
- 접속한 유저가 로그인을 안한 guest면 authority를 guest로 지정.
- 글 조회
- 비 로그인 사용자 : guest
- 로그인 사용자 이나, 사용자의 id와 글 작성한 회원의 id가 다른 경우 : commentOnly
- 단 이 때 authority가 admin인 경우 authority는 admin으로 수정.
- 각 메서드에 필요한 권한을 확인 및 세팅.
@GetMapping
public String posts(Model model, HttpServletRequest request) {
MemberDto loginMemberDto = getLoginMember(request);
List<Post> posts = postService.findAll();
List<PostDto> postsDto = getPostDtos(posts);
loginMemberDto = checkNonLoginGuest(loginMemberDto);
model.addAttribute("member", loginMemberDto);
model.addAttribute("posts", postsDto);
model.addAttribute("searchForm", new SearchForm());
return "post/posts";
}
@GetMapping("/{postId}")
public String post(@PathVariable("postId") Long postId, Model model, HttpServletRequest request){
Post post = postService.findPostById(postId);
PostDto postDto = post.postToDto();
MemberDto loginMemberDto = getLoginMember(request);
loginMemberDto = checkAuthorization(postId, loginMemberDto);
List<Comment> comments = post.getComments();
List<CommentDto> commentDtos = comments.stream()
.map(comment -> new CommentDto(comment.getId(), comment.getContent(), comment.getMember().memberToDto(),
postDto.getId(), comment.getLastModifiedDate())).collect(Collectors.toList());
model.addAttribute("member", loginMemberDto);
model.addAttribute("post", postDto);
model.addAttribute("comments", commentDtos);
model.addAttribute("commentDto", new CommentDto());
return "post/post";
}
@GetMapping("/search")
public String search(@RequestParam("keyword") String keyword, Model model, HttpServletRequest request){
log.info("keyword: {}", keyword);
MemberDto loginMemberDto = getLoginMember(request);
List<Post> posts = postService.findByTitleContains(keyword);
List<PostDto> postsDto = getPostDtos(posts);
checkNonLoginGuest(loginMemberDto);
model.addAttribute("member", loginMemberDto);
model.addAttribute("posts", postsDto);
model.addAttribute("searchForm", new SearchForm(keyword));
model.addAttribute("status", status);
return "post/posts";
}
@GetMapping("/new/form")
public String postForm(Model model, HttpServletRequest request) {
MemberDto loginMemberDto = getLoginMember(request);
if (hasNoAuthority(loginMemberDto)) return "redirect:/posts";
PostDto postDto = new PostDto();
model.addAttribute("member", loginMemberDto);
model.addAttribute("post", postDto);
return "post/addform";
}
@PostMapping("/new/form")
public String addPost(@ModelAttribute("post") PostDto postDto, HttpServletRequest request) {
MemberDto loginMemberDto = getLoginMember(request);
if (hasNoAuthority(loginMemberDto)) return "redirect:/posts";
Member findMember = memberService.findMemberById(loginMemberDto.getId());
log.info("post1.title : {}", postDto.getTitle());
log.info("post1.content : {}", postDto.getContent());
Post post = new Post().dtoToPost(postDto);
post.setMember(findMember);
postService.savePost(post);
memberService.joinMember(findMember);
log.info("new post.title = {}", post.getTitle());
log.info("new post.content = {}", post.getContent());
log.info("new post by : {}", loginMemberDto.getUserId());
return "redirect:/posts";
}
@PostMapping("/{postId}/delete")
public String deletePost(@PathVariable("postId") Long postId, HttpServletRequest request){
MemberDto loginMemberDto = getLoginMember(request);
if (hasNoAuthority(loginMemberDto)) return "redirect:/posts";
PostDto postDto = postService.findPostById(postId).postToDto();
postService.deletePost(postId);
return "redirect:/posts";
}
@GetMapping("/{postId}/edit")
public String editForm(@PathVariable("postId") Long postId, HttpServletRequest request, Model model){
MemberDto loginMemberDto = getLoginMember(request);
if (hasNoAuthority(loginMemberDto)) return "redirect:/posts";
getLoginMemberAndAddToModel(request, model);
PostDto postDto = postService.findPostById(postId).postToDto();
model.addAttribute("post", postDto);
return "post/editform";
}
@PostMapping("/{postId}/edit")
public String editPost(@PathVariable("postId") Long id, @ModelAttribute("post") PostDto postDto
,HttpServletRequest request,Model model, RedirectAttributes redirectAttributes){
MemberDto loginMemberDto = getLoginMember(request);
if (hasNoAuthority(loginMemberDto)) return "redirect:/posts";
Post post = editPostUsingDto(id, postDto);
model.addAttribute("member", loginMemberDto);
model.addAttribute("post", post.postToDto());
redirectAttributes.addAttribute("postID", postDto.getId());
return "redirect:/posts/{postId}";
}
private boolean hasNoAuthority(MemberDto loginMemberDto) {
if (loginMemberDto == null || loginMemberDto.getAuthority().equals(Authority.guest)) {
return true;
}
return false;
}
private MemberDto checkNonLoginGuest(MemberDto loginMemberDto) {
if (loginMemberDto == null){
log.info("비 로그인 사용자 접속");
loginMemberDto = new MemberDto();
loginMemberDto.setUserId(Authority.guest);
loginMemberDto.setAuthority(Authority.guest);
}
return loginMemberDto;
}
private MemberDto checkAuthorization(Long postId, MemberDto loginMemberDto) {
PostDto postDto = postService.findPostById(postId).postToDto();
if (loginMemberDto == null){
log.info("비 로그인 사용자 접속");
loginMemberDto = new MemberDto();
loginMemberDto.setUserId(guest);
loginMemberDto.setAuthority(Authority.guest);
return loginMemberDto;
}else if(!loginMemberDto.getId().equals(postDto.getMember().getId())){
if(loginMemberDto.getAuthority().equals(Authority.admin)){
loginMemberDto.setAuthority(Authority.admin);
return loginMemberDto;
}
loginMemberDto.setAuthority(Authority.commentOnly);
return loginMemberDto;
}else {
loginMemberDto.setAuthority(Authority.normal);
return loginMemberDto;
}
}
5.View
- 글 수정 : guest 이거나 commentOnly인 경우 권한 없음.
<button class="btn btn-primary" type="button"
th:disabled="${member.authority.equals('guest') or member.authority.equals('commentOnly')}"
th:onclick="|location.href='@{/posts/{postId}/edit(postId=${post.id})}'|">수정</button>
- 글 삭제 : guest 이거나 commentOnly인 경우 권한 없음.
<button class="btn btn-secondary float-end" type="submit"
th:disabled="${member.authority.equals('guest') or member.authority.equals('commentOnly')}"
th:onclick="|location.href='@{/posts/{postId}/delete(postId=${post.id})}'|">삭제</button>
- 댓글 삭제 : member.id와 comment.member.id가 동일하거나 admin인 경우 가능
--> admin 이고 member.id와 comment.member.id가 동일하지 않으면 권한 없음.
<form th:action="@{/comments/{commentId}/delete?postId={id}(commentId=${comment.id}, id=${post.id})}" th:object="${commentDto}" method="post">
<button type="submit" class="btn-close" aria-label="Close"
th:disabled="${member.id} != ${comment.member.id} and ${member.authority} !='admin'"></button>
</form>
- 댓글 입력 : guest인 경우만 권한 없음.
<div class="input-group mb-3; form-group">
<input type="text" class="form-control" th:field="*{content}" id="commentString" placeholder="댓글 입력" aria-label="Recipient's username" aria-describedby="button-addon2">
<button class="btn btn-outline-primary" type="submit" id="button-addon2" th:disabled="${member.userId}=='guest'">입력</button>
</div>
6. 결과
- admin으로 접속한 경우 모든 버튼이 활성화 되어 있음.
- test로 로그인 한 경우 test1이 작성한 글/댓글에 대한 권한 없음.
- 본인이 작성한 글/댓글에 대한 권한 있음. 어.. 근데 직접 접속하면 가능하다..
- guest인 경우 모든 권한 없음.
7. url 직접 접속을 통한 다른 사용자 글 수정시도 차단
- editForm()에서 사용할 검증 로직을 살짝 보완 해 주자.
- 해당 글에 권한이 없어도 현재는 url을 통해 수정이 가능한 상태이다.
- 해당 url에 접속하여 editForm()을 호출하는 경우 사용자가 권한이 있는지 재확인 하자.
@GetMapping("/{postId}/edit")
public String editForm(@PathVariable("postId") Long postId, HttpServletRequest request, Model model){
MemberDto loginMemberDto = getLoginMember(request);
PostDto postDto = postService.findPostById(postId).postToDto();
log.info("authority : {}", loginMemberDto.getAuthority());
if (hasNoAuthority(loginMemberDto, postDto)) return "redirect:/posts";
getLoginMemberAndAddToModel(request, model);
model.addAttribute("post", postDto);
return "post/editform";
}
private boolean hasNoAuthority(MemberDto loginMemberDto, PostDto postDto) {
if (loginMemberDto == null || loginMemberDto.getAuthority().equals(Authority.guest)
|| loginMemberDto.getId() != postDto.getMember().getId()) {
return true;
}
return false;
}
8. 앞으로
est용 data 서버시작할 때 DB에 올리기Listener
createdAt, updatedAt등
게시글에 작성자 표시view 정리게시글 검색- 검색 옵션 추가 : 작성자, 제목 구분
영속성 전이 설정게시글 삭제회원 탈퇴
댓글 삭제 버튼글 수정 기능 추가- 대댓글
- 검증 & 예외처리
회원 가입시 필수 정보 지정.특수문자, 공백 검증 등(email 형식?)- Spring제공 Validator로 변경.
인증처리로그인한 사용자만 글 & 댓글 작성 가능.본인이 작성한 글, 댓글만 수정/삭제 가능관리자는 모든 권한
- 예외처리
- 페이징 처리
- 컬렉션 조회 최적화
9. GItHub: 211014 admin
'Project > 블로그 게시판 만들기' 카테고리의 다른 글
Test 추가, gerResultList() (0) | 2021.10.16 |
---|---|
SpringInterceptor (0) | 2021.10.15 |
인증처리 - 본인이 작성한 것만.. (0) | 2021.10.13 |
비 로그인 사용자 처리 (0) | 2021.10.12 |
특수문자 및 공백 검증 (0) | 2021.10.12 |
Comments