From 6a59d1a5411981516a6ede642c1d0352b2ee7113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=8C=E1=85=B5=E1=86=AB=E1=84=89?= =?UTF-8?q?=E1=85=A5=E1=86=A8?= Date: Mon, 3 Feb 2020 10:58:45 +0900 Subject: [PATCH] =?UTF-8?q?=EC=93=B0=EA=B8=B0=20=EB=93=A4=EC=96=B4?= =?UTF-8?q?=EA=B0=80=EC=95=BC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/front/src/middlewares/authentication.js | 16 ++++++++++++++ .../pages/articles/{index.vue => List.vue} | 20 +++++++++++++++--- src/front/src/pages/articles/Write.vue | 21 +++++++++++++++++++ src/front/src/pages/auth/Login.vue | 1 + src/front/src/routes/index.js | 7 ++++++- .../security/JwtAuthenticationFilter.java | 12 +++++++++-- .../example/vue/domain/article/Article.java | 16 ++++++++++++++ .../vue/domain/article/ArticleController.java | 13 +++++++----- .../vue/domain/article/ArticleRepository.java | 5 +++++ .../vue/domain/article/ArticleRequestDto.java | 15 +++++++++++++ .../vue/domain/article/ArticleService.java | 6 +++++- .../vue/domain/auth/AuthException.java | 8 +++++++ 12 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 src/front/src/middlewares/authentication.js rename src/front/src/pages/articles/{index.vue => List.vue} (50%) create mode 100644 src/front/src/pages/articles/Write.vue create mode 100644 src/main/java/com/example/vue/domain/article/ArticleRequestDto.java diff --git a/src/front/src/middlewares/authentication.js b/src/front/src/middlewares/authentication.js new file mode 100644 index 0000000..094ac75 --- /dev/null +++ b/src/front/src/middlewares/authentication.js @@ -0,0 +1,16 @@ +import axios from "axios"; + +export default async function () { + try { + const token = this.$cookie.get('accessToken'); + const result = await axios({ + method: 'get', + url: '/api/users', + headers: { + 'Authorization': 'Bearer ' + token + } + }); + } catch (e) { + + } +} \ No newline at end of file diff --git a/src/front/src/pages/articles/index.vue b/src/front/src/pages/articles/List.vue similarity index 50% rename from src/front/src/pages/articles/index.vue rename to src/front/src/pages/articles/List.vue index c563391..9284531 100644 --- a/src/front/src/pages/articles/index.vue +++ b/src/front/src/pages/articles/List.vue @@ -1,15 +1,22 @@ + + \ No newline at end of file diff --git a/src/front/src/pages/auth/Login.vue b/src/front/src/pages/auth/Login.vue index 655332f..d4ea0a6 100644 --- a/src/front/src/pages/auth/Login.vue +++ b/src/front/src/pages/auth/Login.vue @@ -32,6 +32,7 @@ const result = await authApi.login({email, password}); const { token } = result.data; this.$cookie.set('accessToken', token, 1000); + await this.$router.push('/articles'); } catch (err) { console.log(err); } diff --git a/src/front/src/routes/index.js b/src/front/src/routes/index.js index cb6e722..164cc89 100644 --- a/src/front/src/routes/index.js +++ b/src/front/src/routes/index.js @@ -4,7 +4,8 @@ import VueRouter from "vue-router"; import Welcome from "../pages/Welcome"; import Login from "../pages/auth/Login"; import Register from "../pages/auth/Register"; -import Articles from "../pages/articles"; +import Articles from "../pages/articles/List"; +import WriteArticle from '../pages/articles/Write'; Vue.use(VueRouter); @@ -26,6 +27,10 @@ export const router = new VueRouter({ { path: '/articles', component: Articles + }, + { + path: '/articles/write', + component: WriteArticle } ] }); diff --git a/src/main/java/com/example/vue/config/security/JwtAuthenticationFilter.java b/src/main/java/com/example/vue/config/security/JwtAuthenticationFilter.java index 7ec433c..c780515 100644 --- a/src/main/java/com/example/vue/config/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/example/vue/config/security/JwtAuthenticationFilter.java @@ -1,8 +1,10 @@ package com.example.vue.config.security; +import com.example.vue.domain.auth.AuthException; import com.example.vue.domain.user.User; import com.example.vue.util.JwtUtil; import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtException; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -31,6 +33,7 @@ public class JwtAuthenticationFilter extends BasicAuthenticationFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + Authentication authentication = getAuthentication(request); if (authentication != null) { @@ -49,13 +52,18 @@ public class JwtAuthenticationFilter extends BasicAuthenticationFilter { return null; } - Claims claims = jwtUtil.getClaims(token.substring("Bearer ".length())); + Claims claims; + + try { + claims = jwtUtil.getClaims(token.substring("Bearer ".length())); + } catch (JwtException e) { + throw new AuthException.MalformedJwt(token); + } Set roles = new HashSet<>(); String role = (String) claims.get("role"); roles.add(new SimpleGrantedAuthority("ROLE_" + role)); -// return new UsernamePasswordAuthenticationToken(claims, null, roles); return new UsernamePasswordAuthenticationToken(new User(claims), null, roles); } diff --git a/src/main/java/com/example/vue/domain/article/Article.java b/src/main/java/com/example/vue/domain/article/Article.java index 754160d..56bda6f 100644 --- a/src/main/java/com/example/vue/domain/article/Article.java +++ b/src/main/java/com/example/vue/domain/article/Article.java @@ -1,6 +1,7 @@ package com.example.vue.domain.article; import lombok.Getter; +import lombok.NoArgsConstructor; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -10,6 +11,7 @@ import java.time.LocalDateTime; @Entity @Getter @NamedQuery(name = "findAll", query = "select a from Article a order by a.createdAt desc") +@NoArgsConstructor public class Article { @Id @GeneratedValue @@ -27,4 +29,18 @@ public class Article { @LastModifiedDate private LocalDateTime updatedAt; + public Article(ArticleRequestDto articleRequestDto) { + this.title = articleRequestDto.getTitle(); + this.content = articleRequestDto.getContent(); + } + + @PrePersist + private void prePersist() { + this.createdAt = LocalDateTime.now(); + } + + @PreUpdate + private void preUpdate() { + this.updatedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/example/vue/domain/article/ArticleController.java b/src/main/java/com/example/vue/domain/article/ArticleController.java index 11bcff6..7709cac 100644 --- a/src/main/java/com/example/vue/domain/article/ArticleController.java +++ b/src/main/java/com/example/vue/domain/article/ArticleController.java @@ -2,10 +2,9 @@ package com.example.vue.domain.article; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import javax.validation.Valid; import java.util.List; @RestController @@ -17,7 +16,11 @@ public class ArticleController { @GetMapping public List getArticles(Pageable pageable) { - List articles = articleService.findAll(pageable); - return articles; + return articleService.findAll(pageable); + } + + @PostMapping + public ArticleResponseDto postArticles(@RequestBody @Valid ArticleRequestDto articleRequestDto) { + return articleService.save(articleRequestDto); } } diff --git a/src/main/java/com/example/vue/domain/article/ArticleRepository.java b/src/main/java/com/example/vue/domain/article/ArticleRepository.java index 6387088..ea05720 100644 --- a/src/main/java/com/example/vue/domain/article/ArticleRepository.java +++ b/src/main/java/com/example/vue/domain/article/ArticleRepository.java @@ -14,6 +14,11 @@ public class ArticleRepository { private final EntityManager em; + public Article save(Article article) { + em.persist(article); + return article; + } + public List
findAll(Pageable pageable) { int page = pageable.getPageNumber(); int size = pageable.getPageSize(); diff --git a/src/main/java/com/example/vue/domain/article/ArticleRequestDto.java b/src/main/java/com/example/vue/domain/article/ArticleRequestDto.java new file mode 100644 index 0000000..14a833f --- /dev/null +++ b/src/main/java/com/example/vue/domain/article/ArticleRequestDto.java @@ -0,0 +1,15 @@ +package com.example.vue.domain.article; + +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +public class ArticleRequestDto { + + @NotNull + private String title; + + @NotNull + private String content; +} diff --git a/src/main/java/com/example/vue/domain/article/ArticleService.java b/src/main/java/com/example/vue/domain/article/ArticleService.java index 1c0376a..f315817 100644 --- a/src/main/java/com/example/vue/domain/article/ArticleService.java +++ b/src/main/java/com/example/vue/domain/article/ArticleService.java @@ -1,7 +1,6 @@ package com.example.vue.domain.article; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -14,6 +13,11 @@ public class ArticleService { private final ArticleRepository articleRepository; + public ArticleResponseDto save(ArticleRequestDto articleRequestDto) { + Article article = articleRepository.save(new Article(articleRequestDto)); + return new ArticleResponseDto(article); + } + public List findAll(Pageable pageable) { return articleRepository.findAll(pageable) .stream() diff --git a/src/main/java/com/example/vue/domain/auth/AuthException.java b/src/main/java/com/example/vue/domain/auth/AuthException.java index 5998d8f..5e1bdd6 100644 --- a/src/main/java/com/example/vue/domain/auth/AuthException.java +++ b/src/main/java/com/example/vue/domain/auth/AuthException.java @@ -1,5 +1,6 @@ package com.example.vue.domain.auth; +import io.jsonwebtoken.JwtException; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @@ -25,4 +26,11 @@ public class AuthException { super("이미 존재하는 사용자입니다. [email=" + email + "]"); } } + + @ResponseStatus(HttpStatus.BAD_REQUEST) + public static class MalformedJwt extends JwtException { + public MalformedJwt(String token) { + super("올바르지 않은 토큰 입니다. [token=" + token + "]"); + } + } }