{"id":205,"date":"2020-03-15T15:54:34","date_gmt":"2020-03-15T06:54:34","guid":{"rendered":"http:\/\/www.skyer9.pe.kr\/wordpress\/?p=205"},"modified":"2021-07-16T14:35:32","modified_gmt":"2021-07-16T05:35:32","slug":"from-hello-to-querydsl-google-oauth2-login-9-12","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=205","title":{"rendered":"[From Hello To QueryDSL] Spring Boot Security (9\/12)"},"content":{"rendered":"<h1>Spring Boot Security<\/h1>\n<h2>\uac1c\ubc1c\ud658\uacbd<\/h2>\n<ul>\n<li>Spring Boot 2.1.x<\/li>\n<li>Gradle 4.10.2<\/li>\n<\/ul>\n<h2>build.gradle \uc218\uc815<\/h2>\n<p>build.gradle<\/p>\n<pre><code class=\"language-configuration\">......\ndependencies {\n    \/\/ ......\n    \/\/compile(&#039;org.springframework.boot:spring-boot-starter-security&#039;)\n    \/\/testCompile(&quot;org.springframework.security:spring-security-test&quot;)\n    implementation &#039;org.springframework.boot:spring-boot-starter-security&#039;\n    testImplementation &quot;org.springframework.security:spring-security-test&quot;\n    \/\/ ......\n}\n......<\/code><\/pre>\n<p><a href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a> \uc5d0 \uc811\uc18d\ud558\uba74 \uc544\uc774\ub514\uc640 \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud558\ub77c\uace0 \ud569\ub2c8\ub2e4.<\/p>\n<p>\ub514\ud3f4\ud2b8 \uc544\uc774\ub514\ub294 <code>user<\/code> \uc774\uace0, \ub514\ud3f4\ud2b8 \ube44\ubc00\ubc88\ud638\ub294 \ub85c\uadf8\uc5d0 \uc544\ub798\uc640 \uac19\uc774 \ud45c\uc2dc\ub429\ub2c8\ub2e4.<\/p>\n<pre><code>2020-03-21 15:47:05.526  INFO 14884 --- [           main] .s.s.UserDetailsServiceAutoConfiguration :\n\nUsing generated security password: aa921732-e591-4632-b583-a1547910862c\n\n2020-03-21 15:47:05.698  INFO 14884 --- [           main] o.s.s.web.DefaultSecurityFilterChain     ......<\/code><\/pre>\n<h2>\ucee4\uc2a4\ud140 \ub85c\uadf8\uc778<\/h2>\n<p>\ucee4\uc2a4\ud140 \uc544\uc774\ub514\/\ud328\uc2a4\uc6cc\ub4dc \ub370\uc774\ud0c0\ubca0\uc774\uc2a4\ub97c \uc0dd\uc131\ud558\uace0, \ub4f1\ub85d\ub41c \uc544\uc774\ub514\ub85c \ub85c\uadf8\uc778\ud558\ub3c4\ub85d \uc218\uc815\ud569\ub2c8\ub2e4.<\/p>\n<h3>\ud14c\uc774\ube14 \uc0dd\uc131<\/h3>\n<pre><code class=\"language-sql\">DROP TABLE `user`;\n\nCREATE TABLE `user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT,\n  `email` varchar(255) NOT NULL,\n  `name` varchar(255) NOT NULL,\n  `picture` varchar(255) DEFAULT NULL,\n  `role` varchar(255) NOT NULL,\n  `passwd` varchar(255) NULL,\n  `encpasswd` varchar(255) NULL,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\nINSERT INTO `user`(email,name, role, passwd)\nVALUES(&#039;test@gmail.com&#039;, &#039;\ud14c\uc2a4\ud2b8&#039;, &#039;USER&#039;, &#039;{noop}aa921732-e591-4632-b583-a1547910862c&#039;);<\/code><\/pre>\n<h3>user \uc5d4\ud130\ud2f0 \uc0dd\uc131<\/h3>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/user\/Role.java<\/p>\n<pre><code class=\"language-java\">@Getter\n@RequiredArgsConstructor\npublic enum Role {\n\n    GUEST(&quot;ROLE_GUEST&quot;, &quot;\uc190\ub2d8&quot;),\n    USER(&quot;ROLE_USER&quot;, &quot;\uc77c\ubc18 \uc0ac\uc6a9\uc790&quot;),\n    ADMIN(&quot;ROLE_ADMIN&quot;, &quot;\uad00\ub9ac\uc790&quot;);\n\n    private final String key;\n    private final String title;\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/user\/User.java<\/p>\n<pre><code class=\"language-java\">@Getter\n@NoArgsConstructor\n@Entity\npublic class User {\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private Long id;\n\n    @Column(nullable = false)\n    private String name;\n\n    @Column(nullable = false)\n    private String email;\n\n    @Column\n    private String picture;\n\n    @Enumerated(EnumType.STRING)\n    @Column(nullable = false)\n    private Role role;\n\n    @Column\n    private String passwd;\n\n    @Builder\n    public User(String name, String email, String picture, Role role, String passwd) {\n        this.name = name;\n        this.email = email;\n        this.picture = picture;\n        this.role = role;\n        this.passwd = passwd;\n    }\n\n    public User update(String name, String picture) {\n        this.name = name;\n        this.picture = picture;\n\n        return this;\n    }\n\n    public String getRoleKey() {\n        return this.role.getKey();\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/domain\/user\/UserRepository.java<\/p>\n<pre><code class=\"language-java\">public interface UserRepository extends JpaRepository&lt;User, Long&gt; {\n\n    Optional&lt;User&gt; findByEmail(String email);\n}<\/code><\/pre>\n<h3>user \uc11c\ube44\uc2a4 \uc0dd\uc131<\/h3>\n<p>src\/main\/java\/kr\/co\/episode\/example\/service\/user\/UserService.java<\/p>\n<pre><code class=\"language-java\">@Service\n@RequiredArgsConstructor\npublic class UserService implements UserDetailsService {\n\n    private final UserRepository userRepository;\n\n    @Override\n    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {\n        Optional&lt;User&gt; userWrapper = userRepository.findByEmail(email);\n\n        if(userWrapper.isEmpty()) {\n            throw new UsernameNotFoundException(&quot;Username not found&quot;);\n        }\n\n        User user = userWrapper.get();\n\n        List&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;&gt;();\n\n        if ((&quot;admin@example.com&quot;).equals(email)) {\n            authorities.add(new SimpleGrantedAuthority(Role.ADMIN.getKey()));\n        } else {\n            authorities.add(new SimpleGrantedAuthority(Role.USER.getKey()));\n        }\n\n        return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPasswd(), authorities);\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/SecurityConfig.java<\/p>\n<pre><code class=\"language-java\">@Configuration\n@EnableWebSecurity\n@RequiredArgsConstructor\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n    private final UserService userService;\n\n    @Override\n    protected void configure(HttpSecurity httpSecurity) throws Exception {\n        httpSecurity.csrf().disable()\n                .headers().frameOptions().disable()\n                .and()\n                    .authorizeRequests()\n                    .antMatchers(&quot;\/&quot;, &quot;\/css\/**&quot;, &quot;\/images\/**&quot;, &quot;\/js\/**&quot;, &quot;\/login&quot;, &quot;\/profile&quot;).permitAll()\n                    .antMatchers(&quot;\/api\/v1\/**&quot;, &quot;\/posts\/save&quot;).hasRole(Role.USER.name())\n                    .anyRequest().authenticated()\n                .and()\n                    .logout()\n                    .logoutSuccessUrl(&quot;\/&quot;)\n                .and()\n                    .formLogin();\n    }\n\n    @Override\n    public void configure(AuthenticationManagerBuilder auth) throws Exception {\n        auth.userDetailsService(userService);\n    }\n}<\/code><\/pre>\n<p>\uc704 \uc124\uc815\uc73c\ub85c \ub370\uc774\ud0c0\ubca0\uc774\uc2a4\uc5d0 \uc785\ub825\ud55c \uacc4\uc815\uc815\ubcf4\ub97c \uc774\uc6a9\ud574 \ub85c\uadf8\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\uc138\uc158\uc815\ubcf4 \uc774\uc6a9\ud558\uae30<\/h2>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/dto\/SessionUserDto.java<\/p>\n<pre><code class=\"language-java\">@Getter\npublic class SessionUserDto implements Serializable {\n\n    private String name;\n    private String email;\n    private String picture;\n\n    public SessionUserDto(User user) {\n        this.name = user.getName();\n        this.email = user.getEmail();\n        this.picture = user.getPicture();\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/service\/user\/UserService.java<\/p>\n<pre><code class=\"language-java\">@Service\n@RequiredArgsConstructor\npublic class UserService implements UserDetailsService {\n\n    private final UserRepository userRepository;\n    private final HttpSession httpSession;\n\n    @Override\n    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {\n        \/\/ ......\n\n        List&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;&gt;();\n        httpSession.setAttribute(&quot;user&quot;, new SessionUserDto(user));\n\n        \/\/ ......\n\n        return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPasswd(), authorities);\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/IndexController.java<\/p>\n<pre><code class=\"language-java\">@RequiredArgsConstructor\n@Controller\npublic class IndexController {\n\n    \/\/ ......\n    private final HttpSession httpSession;\n\n    @GetMapping(&quot;\/&quot;)\n    public String index(Model model, @PageableDefault Pageable pageable, @RequestParam Map&lt;String, String&gt; params) {\n        \/\/ ......\n\n        SessionUserDto sessionUserDto = (SessionUserDto) httpSession.getAttribute(&quot;user&quot;);\n        if (sessionUserDto != null) {\n            model.addAttribute(&quot;userName&quot;, sessionUserDto.getName());\n        }\n\n        model.addAttribute(&quot;posts&quot;, postsPagingService.findAllDesc(pageable, postsSearchDto));\n        model.addAttribute(&quot;search&quot;, postsSearchDto);\n\n        return &quot;index&quot;;\n    }\n\n    \/\/ ......\n}<\/code><\/pre>\n<p>src\/main\/resources\/templates\/index.html<\/p>\n<pre><code class=\"language-html\">&lt;div class=&quot;col-md-12&quot;&gt;\n    &lt;div class=&quot;row&quot;&gt;\n        &lt;div class=&quot;col-md-6&quot;&gt;\n            &lt;a href=&quot;\/posts\/save&quot; role=&quot;button&quot; class=&quot;btn&quot; btn-primary&gt;\uae00 \ub4f1\ub85d&lt;\/a&gt;\n            &lt;div th:if=&quot;${userName != null}&quot; th:inline=&quot;text&quot;&gt;\n                [[${userName}]] \ub2d8, \uc548\ub155\ud558\uc138\uc694.\n                &lt;a href=&quot;\/logout&quot; class=&quot;btn btn-info active&quot; role=&quot;button&quot;&gt;\ub85c\uadf8\uc544\uc6c3&lt;\/a&gt;\n            &lt;\/div&gt;\n            &lt;div th:if=&quot;${userName == null}&quot;&gt;\n                &lt;a href=&quot;\/login&quot; class=&quot;btn btn-success active&quot; role=&quot;button&quot;&gt;\ub85c\uadf8\uc778&lt;\/a&gt;\n            &lt;\/div&gt;\n        &lt;\/div&gt;\n    &lt;\/div&gt;\n&lt;\/div&gt;<\/code><\/pre>\n<h2>\uc138\uc158\uc815\ubcf4 \uc5b4\ub178\ud14c\uc774\uc158\uc73c\ub85c \uac00\uc838\uc624\uae30<\/h2>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/LoginUser.java<\/p>\n<pre><code class=\"language-java\">@Target(ElementType.PARAMETER)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface LoginUser {\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/LoginUserArgumentResolver.java<\/p>\n<pre><code class=\"language-java\">@RequiredArgsConstructor\n@Component\npublic class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {\n\n    private final HttpSession httpSession;\n\n    @Override\n    public boolean supportsParameter(MethodParameter parameter) {\n        boolean isLoginUserAnnotation = parameter.getParameterAnnotation(LoginUser.class) != null;\n        boolean isUserClass = SessionUserDto.class.equals(parameter.getParameterType());\n\n        return isLoginUserAnnotation &amp;&amp; isUserClass;\n    }\n\n    @Override\n    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {\n        return httpSession.getAttribute(&quot;user&quot;);\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/config\/WebConfig.java<\/p>\n<pre><code class=\"language-java\">@RequiredArgsConstructor\n@Configuration\npublic class WebConfig implements WebMvcConfigurer {\n\n    private final LoginUserArgumentResolver loginUserArgumentResolver;\n\n    @Override\n    public void addArgumentResolvers(List&lt;HandlerMethodArgumentResolver&gt; resolvers) {\n        resolvers.add(loginUserArgumentResolver);\n    }\n}<\/code><\/pre>\n<p>src\/main\/java\/kr\/co\/episode\/example\/web\/IndexController.java<\/p>\n<pre><code class=\"language-java\">@RequiredArgsConstructor\n@Controller\npublic class IndexController {\n\n    \/\/ ......\n\n    @GetMapping(&quot;\/&quot;)\n    public String index(Model model, @PageableDefault Pageable pageable, @LoginUser SessionUserDto user, @RequestParam Map&lt;String, String&gt; params) {\n        \/\/ ......\n\n        if (user != null) {\n            model.addAttribute(&quot;userName&quot;, user.getName());\n        }\n\n        model.addAttribute(&quot;posts&quot;, postsPagingService.search(pageable, postsSearchDto));\n        model.addAttribute(&quot;search&quot;, postsSearchDto);\n\n        return &quot;index&quot;;\n    }\n\n    \/\/ ......\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Spring Boot Security \ub97c \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5 \ud569\ub2c8\ub2e4.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-205","post","type-post","status-publish","format-standard","hentry","category-spring-boot-2-1"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/205","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=205"}],"version-history":[{"count":15,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/205\/revisions"}],"predecessor-version":[{"id":2192,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/205\/revisions\/2192"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=205"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=205"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=205"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}