使用SpringBoot和Spring Security OAuth2来自定义OAuth服务器并进行认证

首先

使用的物品 de

    • Eclipse

 

    • Gradle

 

    認証サーバここで作成したもの

安装

    • Eclipse Market Placeから

Gradle IDE Pack
Spring Tool Suite

项目设置

完成项目

    • Eclipse – File – New – Project…

 

    • Gradle – Gradle Project

 

    Project nameに任意の名前、Sample ProjectにJava Quick startを選択
Kobito.7FuXjY.png
    • 不要なパッケージの削除

src/main/java 配下
src/main/resources 配下
src/test/java 配下
src/test/resources 配下

使用 Gradle 安装依赖包

    package version情報を外出しするため、project直下にgradle.propertiesファイルを作成し以下の記述
SPRING_BOOT_VERSION=1.3.2.RELEASE
SPRING_LOADED_VERSION=1.2.5.RELEASE
JAVA_VERSION=1.8
POSTGRES_VERSION=9.4-1200-jdbc41
SPRING_CORE_VERSION=4.2.4.RELEASE
    build.gradleに依存パッケージ情報を記述
buildscript {
    repositories {
      mavenCentral()
      maven {
        url "https://plugins.gradle.org/m2/"
      }
    }
    dependencies {
      classpath "org.springframework.boot:spring-boot-gradle-plugin:${SPRING_BOOT_VERSION}"
      classpath "org.springframework:springloaded:${SPRING_LOADED_VERSION}"
    }
}

apply plugin: 'java'
apply plugin: 'spring-boot'

sourceCompatibility = "${JAVA_VERSION}"
targetCompatibility = "${JAVA_VERSION}"

repositories {
  mavenCentral()
}

jar.baseName = 'springboot-oauth-sample'

dependencies {
    // for web application
    compile "org.springframework.boot:spring-boot-starter-web:${SPRING_BOOT_VERSION}"

    // template engine: jade
    compile "com.domingosuarez.boot:spring-boot-starter-jade4j:0.3.0"

    // use spring security
    compile "org.springframework.boot:spring-boot-starter-security:${SPRING_BOOT_VERSION}"

    // use spring security oauth2
    compile "org.springframework.security.oauth:spring-security-oauth2:2.0.7.RELEASE"

    // use configuration processor
    compile "org.springframework.boot:spring-boot-configuration-processor:1.2.5.RELEASE"

    // use spring core
    compile "org.springframework:spring-core:${SPRING_CORE_VERSION}"

    // use Scribe OAuth
    compile "com.github.scribejava:scribejava-apis:2.2.2"

}

    Project右クリック – Gradle – Refresh All

编码

创建入口点

    src/main/javaを右クリック – New – Package

这次的包名被命名为springboot.oauth.sample。

    作成したパッケージ右クリック – New – Class – Main.javaを作成する
package springboot.oauth.sample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main {

  public static void main(String[] args)  {
    SpringApplication.run(Main.class, args);
  }

}

应用程序设置

    • src/main/resources/application.ymlを作成

 

    • 事前にoauth server側でclientを作成

作成時に取得したclient-idとclient-secretを設定
oauth server側の認証urlも設定する

OAuth側の設定はほぼこれだけであとは勝手に認証処理してくれる

server:
  port: 8080
  session-timeout: 1200

spring:
  main:  
    show-banner: true

security:
  basic:
    enabled: false
  oauth2:
    client:
      client-id: sampleapp
      client-secret: wlpaBFBJTzmRLcLInQcIiS8ggLclLjQg
      access-token-uri: http://localhost:9999/api/oauth2/token
      user-authorization-uri: http://localhost:9999/api/oauth2/authorize
      scope: admin,user
      authorized-grant-types: authorization_code,refresh_token,client_credentials

    resource:
      user-info-uri: http://localhost:9999/api/profile
      prefer-token-info: false

    custom:
      # for single sign out(global logout)
      server-logout-url: http://localhost:9999/logout

      # redirect url for after single signed out
      server-logouted-redirect-url: http://localhost:8080/


春季安全性的设置

    • src/main/java//config/SecurityConfig.java

 

    • spring securityの設定にて認証が必要なurlを設定する

HttpSecurityにセット

spring securityに認証をOAuthサーバに任せるよう@EnableOAuth2Ssoアノテーションをつける

package springboot.oauth.sample.config;

import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;

@Configuration
@EnableWebSecurity
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  @Value("${security.oauth2.custom.server-logout-url}") private String serverLogoutUrl;

  @Value("${security.oauth2.custom.server-logouted-redirect-url}") private String serverLogoutedRedirectUrl;

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http
      .headers()
        // allow iframe
        .addHeaderWriter(new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN))
      .and()
      .authorizeRequests()
      .antMatchers("/public/**").permitAll()
      .antMatchers("/").permitAll()
      .antMatchers("/admin/**").hasRole("ADMIN")
      .anyRequest().authenticated()
      .and()
      .csrf()
        .csrfTokenRepository(csrfTokenRepository())
      .and()
      .logout()
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        .logoutSuccessUrl(serverLogoutUrl + "?next=" + serverLogoutedRedirectUrl)
        .deleteCookies("JSESSIONID")
        .invalidateHttpSession(true)
        .permitAll()
    ;
  }

  private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setHeaderName("X-XSRF-TOKEN");
    return repository;
  }
}

创建控制器

認証が必要なURLを作成

実際はSecurityConfig.javaの設定で認証を必要とするURL
今回は/protectedとした

アクセス時、OAuthサーバへ自動的に認証しにいき、さらに認証OK後、accessTokenを取得、profileを取得するところまで全自動
認証OKでcontrollerに入ってくるので認証情報をOAuth2Authenticationで取得できる


package springboot.oauth.sample.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/protected")
public class ProtectedController extends BaseController {

  @RequestMapping(value = {"", "/"}, method = RequestMethod.GET)
  public Authentication index(OAuth2Authentication authentication) {
    return authentication;
  }
}

我要試試看

登陆

    • ブラウザからlocalhost:8080/protectedにアクセス

 

    自動的にOAuthサーバの認証ページに遷移する
Kobito.Q01sVF.png
    • 認証OKすると以下のことをSpring Securityが自動的にしてくれる

/loginというURLを使いOAuth codeを取得
codeを使ってOAuthサーバにリクエストを投げ、access_tokenを取得
access_tokenを使ってOAuthサーバのprofile apiにアクセスしてprofileを取得
もともとリクエストされたURLに遷移

Kobito.1bghvM.png

退出登录

    • ブラウザからlocalhost:8080/logoutにアクセス

/logoutはSecurityConfigで指定したURLで、spring securityが自動的にurlをマッピングしてくれる

ログアウト後、OAuthサーバのログアウトURLに飛ばしているのでOAuthサーバ側もログアウトされる

この辺は無理やりだけれどglobal logoutってきっとこういうことなんだろうと勝手に解釈

bannerAds