{"id":9301,"date":"2024-08-13T14:45:45","date_gmt":"2024-08-13T05:45:45","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9301"},"modified":"2024-08-18T13:43:55","modified_gmt":"2024-08-18T04:43:55","slug":"spring-authorization-serveroauth2-2024","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9301","title":{"rendered":"spring-authorization-server(Oauth2) 2024 &#8211; 1"},"content":{"rendered":"<h1>spring-authorization-server(Oauth2) 2024 &#8211; 1<\/h1>\n<p>2021 \ub144\ub3c4\uc5d0 \ud14c\uc2a4\ud2b8 \ud574\ubcf4\uace0 3\ub144\uc774 \uc9c0\ub0ac\ub2e4.<br \/>\n\uc774\uc81c\ub294 \uc5bc\ub9c8\ub098 \uc548\uc815\uc801\uc778\uc9c0 \ud655\uc778\ud574 \ubcf4\uace0\uc2f6\uc5c8\ub2e4.<\/p>\n<p>\uc2e4\ud589\ubc29\ubc95\uc740 \uc544\ub798\uc640 \uac19\ub2e4.<\/p>\n<h2>\uc18c\uc2a4 \ub2e4\uc6b4\ub85c\ub4dc<\/h2>\n<p><code>https:\/\/github.com\/spring-projects\/spring-authorization-server<\/code> \uc5d0\uc11c \uc18c\uc2a4\ub97c \ub2e4\uc6b4\ubc1b\ub294\ub2e4.<\/p>\n<h2>\uc0d8\ud50c \uc11c\ubc84 \uc2e4\ud589<\/h2>\n<h3>demo-authorizationserver \uc2e4\ud589<\/h3>\n<pre><code class=\"language-bash\">.\/gradlew -b samples\/demo-authorizationserver\/samples-demo-authorizationserver.gradle bootRun<\/code><\/pre>\n<p>\uacbd\uace0\uac00 \ub728\uc9c0\ub9cc \uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub41c\ub2e4.<\/p>\n<p>\uacbd\uace0\ub97c \uc81c\uac70\ud558\ub824\uba74 \uc544\ub798 \uc758\uc874\uc131\uc744 \ucd94\uac00\ud574 \uc8fc\uba74 \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-gradle\">implementation &#039;com.google.code.findbugs:jsr305:3.0.2&#039;<\/code><\/pre>\n<h3>demo-client \uc2e4\ud589<\/h3>\n<pre><code class=\"language-bash\">.\/gradlew -b samples\/demo-client\/samples-demo-client.gradle bootRun<\/code><\/pre>\n<p>\uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub41c\ub2e4.<\/p>\n<h3>messages-resource \uc2e4\ud589<\/h3>\n<pre><code class=\"language-bash\">.\/gradlew -b samples\/messages-resource\/samples-messages-resource.gradle bootRun<\/code><\/pre>\n<p>\uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub41c\ub2e4.<\/p>\n<h2>\uc811\uc18d<\/h2>\n<p><code>http:\/\/127.0.0.1:8080<\/code> \uc5d0 \uc811\uc18d\ud574 \ubcf8\ub2e4.<br \/>\n\ud06c\ub86c\uc5d0\uc11c \uc811\uc18d\ud558\ub824 \ud558\uba74 \uc624\ub958\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>user1 \\ password<\/p>\n<h2>\ud06c\ub86c \uc811\uc18d \uc624\ub958 \ud574\uacb0<\/h2>\n<p><code>chrome:\/\/net-internals\/#hsts<\/code> \uc5d0 \uc811\uc18d\ud569\ub2c8\ub2e4.<br \/>\nDelete domain security policies \uc5d0 localhost \ub97c \ub4f1\ub85d\ud574 \uc90d\ub2c8\ub2e4.<\/p>\n<p><code>chrome:\/\/flags\/#allow-insecure-localhost<\/code> \uc5d0 \uc811\uc18d\ud569\ub2c8\ub2e4.<br \/>\nlocalhost \uc811\uc18d\uc744 \ud5c8\uc6a9\ud574 \uc90d\ub2c8\ub2e4.<\/p>\n<p><a href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a> \ub85c \uc811\uc18d\ud569\ub2c8\ub2e4.<\/p>\n<h2>\ub85c\uadf8\uc778\/\ub85c\uadf8\uc544\uc6c3 \ucee4\uc2a4\ud130\ub9c8\uc774\uc9d5<\/h2>\n<p>DefaultSecurityConfig.java<\/p>\n<pre><code class=\"language-java\">@Bean\npublic SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)\n        throws Exception {\n    http\n            .authorizeHttpRequests(authorize -&gt;\n                    authorize\n                            .requestMatchers(&quot;\/assets\/**&quot;, &quot;\/login&quot;, &quot;\/error&quot;).permitAll()\n                            .anyRequest().authenticated()\n            )\n            \/\/ \ub85c\uadf8\uc778 \ud398\uc774\uc9c0\n            .formLogin(formLogin -&gt;\n                    formLogin\n                            .loginPage(&quot;\/login&quot;)\n                            .usernameParameter(&quot;username&quot;)\n                            .passwordParameter(&quot;password&quot;)\n                            .successHandler((request, response, authentication) -&gt; {\n                                response.sendRedirect(&quot;\/home&quot;);\n                            })\n            ).logout(logout -&gt;\n                    logout\n                            .logoutUrl(&quot;\/logout&quot;)\n                            .logoutSuccessHandler((request, response, authentication) -&gt; {\n                                response.sendRedirect(&quot;\/&quot;);\n                            })\n            );\n\n    return http.build();\n}<\/code><\/pre>\n<h2>MariaDB \uc0ac\uc6a9<\/h2>\n<p>build.gradle<\/p>\n<pre><code class=\"language-gradle\">dependencies {\n    \/\/ runtimeOnly &quot;com.h2database:h2&quot;\n    runtimeOnly &#039;com.mysql:mysql-connector-j&#039;\n}<\/code><\/pre>\n<p>application.yml<\/p>\n<pre><code class=\"language-yaml\">spring:\n  datasource:\n    url: jdbc:mysql:\/\/${MYSQL_HOST:localhost}:3306\/db_oauth2_test\n    username: root\n    password:\n    driver-class-name: com.mysql.cj.jdbc.Driver\n  jpa:\n    hibernate:\n      ddl-auto: update    # \uac1c\ubc1c\uc6a9 only\n    show-sql: true<\/code><\/pre>\n<p>\uc2a4\ud0a4\ub9c8 \uc0dd\uc131<\/p>\n<pre><code class=\"language-sql\">CREATE TABLE oauth2_registered_client (\n    id varchar(100) NOT NULL,\n    client_id varchar(100) NOT NULL,\n    client_id_issued_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,\n    client_secret varchar(200) DEFAULT NULL,\n    client_secret_expires_at timestamp DEFAULT NULL,\n    client_name varchar(200) NOT NULL,\n    client_authentication_methods varchar(1000) NOT NULL,\n    authorization_grant_types varchar(1000) NOT NULL,\n    redirect_uris varchar(1000) DEFAULT NULL,\n    post_logout_redirect_uris varchar(1000) DEFAULT NULL,\n    scopes varchar(1000) NOT NULL,\n    client_settings varchar(2000) NOT NULL,\n    token_settings varchar(2000) NOT NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE oauth2_authorization_consent (\n    registered_client_id varchar(100) NOT NULL,\n    principal_name varchar(200) NOT NULL,\n    authorities varchar(1000) NOT NULL,\n    PRIMARY KEY (registered_client_id, principal_name)\n);\n\nCREATE TABLE oauth2_authorization (\n    id varchar(100) NOT NULL,\n    registered_client_id varchar(100) NOT NULL,\n    principal_name varchar(200) NOT NULL,\n    authorization_grant_type varchar(100) NOT NULL,\n    authorized_scopes varchar(1000) DEFAULT NULL,\n    attributes blob DEFAULT NULL,\n    state varchar(500) DEFAULT NULL,\n    authorization_code_value blob DEFAULT NULL,\n    authorization_code_issued_at timestamp DEFAULT NULL,\n    authorization_code_expires_at timestamp DEFAULT NULL,\n    authorization_code_metadata blob DEFAULT NULL,\n    access_token_value blob DEFAULT NULL,\n    access_token_issued_at timestamp DEFAULT NULL,\n    access_token_expires_at timestamp DEFAULT NULL,\n    access_token_metadata blob DEFAULT NULL,\n    access_token_type varchar(100) DEFAULT NULL,\n    access_token_scopes varchar(1000) DEFAULT NULL,\n    oidc_id_token_value blob DEFAULT NULL,\n    oidc_id_token_issued_at timestamp DEFAULT NULL,\n    oidc_id_token_expires_at timestamp DEFAULT NULL,\n    oidc_id_token_metadata blob DEFAULT NULL,\n    refresh_token_value blob DEFAULT NULL,\n    refresh_token_issued_at timestamp DEFAULT NULL,\n    refresh_token_expires_at timestamp DEFAULT NULL,\n    refresh_token_metadata blob DEFAULT NULL,\n    user_code_value blob DEFAULT NULL,\n    user_code_issued_at timestamp DEFAULT NULL,\n    user_code_expires_at timestamp DEFAULT NULL,\n    user_code_metadata blob DEFAULT NULL,\n    device_code_value blob DEFAULT NULL,\n    device_code_issued_at timestamp DEFAULT NULL,\n    device_code_expires_at timestamp DEFAULT NULL,\n    device_code_metadata blob DEFAULT NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE users (\n    id INT(10) NOT NULL AUTO_INCREMENT,\n    username VARCHAR(100) NOT NULL,\n    password VARCHAR(200) DEFAULT NULL,\n    enabled BOOLEAN NOT NULL,\n    acc_locked BOOLEAN NULL,\n    acc_expired BOOLEAN NULL,\n    creds_expired BOOLEAN NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE authorities (\n    id INT(10) NOT NULL AUTO_INCREMENT,\n    username VARCHAR(100) NOT NULL,\n    authority VARCHAR(200) NOT NULL,\n    PRIMARY KEY (id)\n);<\/code><\/pre>\n<p>DefaultSecurityConfig.java<\/p>\n<pre><code class=\"language-java\">@Configuration\n@EnableWebSecurity\npublic class DefaultSecurityConfig {\n\n    private final DataSource dataSource;\n\n    @Bean\n    public PasswordEncoder bCryptPasswordEncoder() {\n        return new BCryptPasswordEncoder();\n    }\n\n    public DefaultSecurityConfig(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    @Bean\n    public UserDetailsService userDetailsService() {\n        JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);\n\n        try {\n            UserDetails user = jdbcUserDetailsManager.loadUserByUsername(&quot;user&quot;);\n        } catch (UsernameNotFoundException ex) {\n            PasswordEncoder encoder = new BCryptPasswordEncoder();\n            UserDetails user = User\n                    .withUsername(&quot;user&quot;)\n                    .passwordEncoder(encoder::encode)\n                    .password(&quot;password&quot;)\n                    .roles(&quot;USER&quot;)\n                    .build();\n            jdbcUserDetailsManager.createUser(user);\n        }\n\n        return jdbcUserDetailsManager;\n    }\n}<\/code><\/pre>\n<p>AuthorizationServerConfig.java<\/p>\n<pre><code class=\"language-java\">@Configuration(proxyBeanMethods = false)\npublic class AuthorizationServerConfig {\n    \/\/ ......\n\n    \/\/ @formatter:off\n    @Bean\n    public JdbcRegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {\n        PasswordEncoder encoder = new BCryptPasswordEncoder();\n\n        RegisteredClient messagingClient = RegisteredClient.withId(UUID.randomUUID().toString())\n                .clientId(&quot;messaging-client&quot;)\n                .clientSecret(encoder.encode(&quot;secret&quot;))\n                \/\/ ......\n                .build();\n\n        \/\/ ......\n\n        RegisteredClient tokenExchangeClient = RegisteredClient.withId(UUID.randomUUID().toString())\n                .clientId(&quot;token-client&quot;)\n                .clientSecret(encoder.encode(&quot;token&quot;))\n                \/\/ ......\n                .build();\n\n        \/\/ ......\n\n        \/\/ Save registered client&#039;s in db as if in-memory\n        JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);\n        if (registeredClientRepository.findByClientId(&quot;messaging-client&quot;) == null) {\n            registeredClientRepository.save(messagingClient);\n            registeredClientRepository.save(deviceClient);\n            registeredClientRepository.save(tokenExchangeClient);\n            registeredClientRepository.save(mtlsDemoClient);\n        }\n\n        return registeredClientRepository;\n    }\n    \/\/ @formatter:on\n\n    \/\/ ......\n\n\/\/  @Bean\n\/\/  public EmbeddedDatabase embeddedDatabase() {\n\/\/      \/\/ @formatter:off\n\/\/      return new EmbeddedDatabaseBuilder()\n\/\/              .generateUniqueName(true)\n\/\/              .setType(EmbeddedDatabaseType.H2)\n\/\/              .setScriptEncoding(&quot;UTF-8&quot;)\n\/\/              .addScript(&quot;org\/springframework\/security\/oauth2\/server\/authorization\/oauth2-authorization-schema.sql&quot;)\n\/\/              .addScript(&quot;org\/springframework\/security\/oauth2\/server\/authorization\/oauth2-authorization-consent-schema.sql&quot;)\n\/\/              .addScript(&quot;org\/springframework\/security\/oauth2\/server\/authorization\/client\/oauth2-registered-client-schema.sql&quot;)\n\/\/              .build();\n\/\/      \/\/ @formatter:on\n\/\/  }\n\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>spring-authorization-server(Oauth2) 2024 &#8211; 1 2021 \ub144\ub3c4\uc5d0 \ud14c\uc2a4\ud2b8 \ud574\ubcf4\uace0 3\ub144\uc774 \uc9c0\ub0ac\ub2e4. \uc774\uc81c\ub294 \uc5bc\ub9c8\ub098 \uc548\uc815\uc801\uc778\uc9c0 \ud655\uc778\ud574 \ubcf4\uace0\uc2f6\uc5c8\ub2e4. \uc2e4\ud589\ubc29\ubc95\uc740 \uc544\ub798\uc640 \uac19\ub2e4. \uc18c\uc2a4 \ub2e4\uc6b4\ub85c\ub4dc https:\/\/github.com\/spring-projects\/spring-authorization-server \uc5d0\uc11c \uc18c\uc2a4\ub97c \ub2e4\uc6b4\ubc1b\ub294\ub2e4. \uc0d8\ud50c \uc11c\ubc84 \uc2e4\ud589 demo-authorizationserver \uc2e4\ud589 .\/gradlew -b samples\/demo-authorizationserver\/samples-demo-authorizationserver.gradle bootRun \uacbd\uace0\uac00 \ub728\uc9c0\ub9cc \uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub41c\ub2e4. \uacbd\uace0\ub97c \uc81c\uac70\ud558\ub824\uba74 \uc544\ub798 \uc758\uc874\uc131\uc744 \ucd94\uac00\ud574 \uc8fc\uba74 \ub41c\ub2e4. implementation &#039;com.google.code.findbugs:jsr305:3.0.2&#039; demo-client \uc2e4\ud589 .\/gradlew -b samples\/demo-client\/samples-demo-client.gradle bootRun \uc815\uc0c1\uc801\uc73c\ub85c \uc2e4\ud589\ub41c\ub2e4. messages-resource\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=9301\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[54],"tags":[],"class_list":["post-9301","post","type-post","status-publish","format-standard","hentry","category-spring-boot-3-0"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9301","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=9301"}],"version-history":[{"count":21,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9301\/revisions"}],"predecessor-version":[{"id":9322,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/9301\/revisions\/9322"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=9301"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=9301"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=9301"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}