$ cd simple
$ ../mvnw package
$ java -jar target/*.jar
Spring Boot ãš OAuth2
ãã®ã¬ã€ãã§ã¯ãOAuth 2.0 [IETF] (è±èª) ããã³ Spring Boot ã䜿çšããŠããœãŒã·ã£ã«ãã°ã€ã³ãã§ããŸããŸãªããšãè¡ããµã³ãã«ã¢ããªãäœæããæ¹æ³ã瀺ããŸãã
ã·ã³ãã«ãªã·ã³ã°ã«ãããã€ããŒã·ã³ã°ã«ãµã€ã³ãªã³ããå§ãŸããèªèšŒãããã€ããŒãéžæããã¯ã©ã€ã¢ã³ãïŒGitHub (è±èª) ãŸã㯠Google (è±èª) ïŒãŸã§æ©èœããŸãã
ãµã³ãã«ã¯ãã¹ãŠãããã¯ãšã³ãã§ Spring Boot ãš Spring Security ã䜿çšããã·ã³ã°ã«ããŒãžã¢ããªã§ãããŸããããã³ããšã³ãã§ã¯ãã¬ãŒã³ãª jQuery (è±èª) ã䜿çšããŠããŸãããã ããå¥ã® JavaScript ãã¬ãŒã ã¯ãŒã¯ã«å€æãããããµãŒããŒåŽã¬ã³ããªã³ã°ã䜿çšãããããããã«å¿ èŠãªå€æŽã¯æå°éã§ãã
ãã¹ãŠã®ãµã³ãã«ã¯ãSpring Boot (è±èª) ã®ãã€ãã£ã OAuth 2.0 ãµããŒãã䜿çšããŠå®è£ ãããŸãã
ããã€ãã®ãµã³ãã«ãçžäºã«æ§ç¯ãããŠãããåã¹ãããã§æ°ããæ©èœã远å ãããŠããŸãã
simple: ããŒã ããŒãžãš Spring Boot ã® OAuth 2.0 æ§æããããã£ãä»ããç¡æ¡ä»¶ã®ãã°ã€ã³ãåããéåžžã«åºæ¬çãªéçã¢ããªïŒããŒã ããŒãžã«ã¢ã¯ã»ã¹ãããšãèªåçã« GitHub ã«ãªãã€ã¬ã¯ããããŸãïŒã
click: ãŠãŒã¶ãŒããã°ã€ã³ããããã«ã¯ãªãã¯ããå¿ èŠãããæç€ºçãªãªã³ã¯ã远å ããŸãã
logout: èªèšŒããããŠãŒã¶ãŒã®ãã°ã¢ãŠããªã³ã¯ã远å ããŸãã
two-providers: ãŠãŒã¶ãŒãããŒã ããŒãžã§äœ¿çšãããã®ãéžæã§ããããã«ã2 çªç®ã®ãã°ã€ã³ãããã€ããŒã远å ããŸãã
custom-error: èªèšŒãããŠããªããŠãŒã¶ãŒåãã®ãšã©ãŒã¡ãã»ãŒãžãšãGitHub ã® API ã«åºã¥ãã«ã¹ã¿ã èªèšŒã远å ããŸãã
æ©èœã©ããŒå ã®ããã¢ããªããæ¬¡ã®ã¢ããªã«ç§»è¡ããããã«å¿ èŠãªå€æŽã¯ããœãŒã¹ã³ãŒã [GitHub] (è±èª) ã§è¿œè·¡ã§ããŸããã¢ããªã®åããŒãžã§ã³ã¯ç¬èªã®ãã£ã¬ã¯ããªã§ãããããéããæ¯èŒã§ããŸãã |
åã¢ããªã¯ IDE ã«ã€ã³ããŒãã§ããŸããSocialApplication
ã§ main
ã¡ãœãããå®è¡ããŠã¢ããªãèµ·åã§ããŸãããããã¯ãã¹ãŠãhttp://localhost:8080 ã«ããŒã ããŒãžãäœæããŸã (ãã°ã€ã³ããŠã³ã³ãã³ãã衚瀺ããã«ã¯ãå°ãªããšã GitHub ããã³ Google ã¢ã«ãŠã³ããæã£ãŠããå¿
èŠããããŸã)ã
ãŸããmvn spring-boot:run
ã䜿çšããŠããŸã㯠jar ãã¡ã€ã«ãäœæã㊠mvn package
ããã³ java -jar target/*.jar
ã§å®è¡ããããšã«ãããã³ãã³ãã©ã€ã³ã§ãã¹ãŠã®ã¢ããªãå®è¡ã§ããŸãïŒSpring Boot ããã¥ã¡ã³ã (è±èª) ããã³ãã®ä»ã®å©çšå¯èœãªããã¥ã¡ã³ãã«åŸã£ãŠïŒãæäžäœã§ã©ãã㌠[GitHub] (è±èª) ã䜿çšããå ŽåãMaven ãã€ã³ã¹ããŒã«ããå¿
èŠã¯ãããŸãããããšãã°
ã¢ããªã¯ãã¹ãŠããã®ã¢ãã¬ã¹ã® GitHub ããã³ Google ã«ç»é²ããã OAuth 2.0 ã¯ã©ã€ã¢ã³ãã䜿çšãããããlocalhost:8080 ã§åäœããŸããå¥ã®ãã¹ããŸãã¯ããŒãã§ã¢ããªãå®è¡ããã«ã¯ããã®ããã«ã¢ããªãç»é²ããå¿
èŠããããŸããããã©ã«ãå€ã䜿çšããå ŽåãããŒã«ã«ãã¹ããè¶
ããŠè³æ Œæ
å ±ãæŒæŽ©ããå±éºã¯ãããŸããããã ããäœãã€ã³ã¿ãŒãããã«å
¬éãããã«ã¯æ³šæããç¬èªã®ã¢ããªç»é²ããããªãã¯ãœãŒã¹ç®¡çã«çœ®ããªãã§ãã ããã |
GitHub ã§ã®ã·ã³ã°ã«ãµã€ã³ãªã³
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãèªèšŒã« GitHub ã䜿çšããæå°éã®ã¢ããªã±ãŒã·ã§ã³ãäœæããŸããããã¯ãSpring Boot ã®èªåæ§ææ©èœãå©çšããããšã«ãããéåžžã«ç°¡åã«ãªããŸãã
æ°ãããããžã§ã¯ããäœæãã
ãŸããSpring Boot ã¢ããªã±ãŒã·ã§ã³ãäœæããå¿ èŠããããŸãããããã¯ããŸããŸãªæ¹æ³ã§å®è¡ã§ããŸããæãç°¡åãªæ¹æ³ã¯ãhttps://start.spring.io ã«ç§»åããŠç©ºã®ãããžã§ã¯ããçæããããšã§ãïŒéå§ç¹ãšã㊠"Web" äŸåé¢ä¿ãéžæããŸãïŒãåæ§ã«ãã³ãã³ãã©ã€ã³ã§ãããå®è¡ããŸãã
$ mkdir ui && cd ui
$ curl https://start.spring.io/starter.tgz -d style=web -d name=simple | tar -xzvf -
ãã®åŸããã®ãããžã§ã¯ãããæ°ã«å
¥ãã® IDEïŒããã©ã«ãã§ã¯éåžžã® Maven Java ãããžã§ã¯ãïŒã«ã€ã³ããŒãããããã³ãã³ãã©ã€ã³ã§ãã¡ã€ã«ãš mvn
ãæäœããã ãã§ãã
ããŒã ããŒãžã远å ãã
æ°ãããããžã§ã¯ãã§ãsrc/main/resources/static
ãã©ã«ããŒã« index.html
ãäœæããŸããçµæãæ¬¡ã®ããã«ãªãããã«ãã¹ã¿ã€ã«ã·ãŒããš JavaScript ãªã³ã¯ã远å ããå¿
èŠããããŸãã
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<title>Demo</title>
<meta name="description" content=""/>
<meta name="viewport" content="width=device-width"/>
<base href="/"/>
<link rel="stylesheet" type="text/css" href="/webjars/bootstrap/css/bootstrap.min.css"/>
<script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Demo</h1>
<div class="container"></div>
</body>
</html>
OAuth 2.0 ãã°ã€ã³æ©èœããã¢ã³ã¹ãã¬ãŒã·ã§ã³ããããã«ããã¯å¿ èŠãããŸããããæåŸã«å¿«é©ãª UI ãçšæããã®ã¯è¯ãããšãªã®ã§ãããŒã ããŒãžã®åºæ¬çãªãã®ããå§ããããšãã§ããŸãã
ã¢ããªãèµ·åããŠããŒã ããŒãžãèªã¿èŸŒããšãã¹ã¿ã€ã«ã·ãŒããèªã¿èŸŒãŸããŠããªãããšã«æ°ãä»ãã§ãããããã®ãããjQuery ãš Twitter Bootstrap ã远å ããŠããããã远å ããå¿ èŠããããŸãã
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
æåŸã®äŸåé¢ä¿ã¯ãwebjars ãµã€ãã«ãã£ãŠã©ã€ãã©ãªãšããŠæäŸããã webjarsããã±ãŒã¿ãŒãã§ããSpring ã¯ãã±ãŒã¿ãŒã䜿çšããŠãæ£ç¢ºãªããŒãžã§ã³ãç¥ãå¿
èŠãªã webjar å
ã®éçã¢ã»ãããèŠã€ããããšãã§ããŸãïŒãããã£ãŠãindex.html
ã®ããŒãžã§ã³ã¬ã¹ /webjars/**
ãªã³ã¯ïŒãMVC èªåæ§æããªãã«ããªãéããSpring Boot ã¢ããªã§ã¯ webjar ãã±ãŒã¿ãŒãããã©ã«ãã§ã¢ã¯ãã£ãã«ãªããŸãã
ãããã®å€æŽãé©åã«è¡ããããšãã¢ããªã®èŠæ ãã®è¯ãããŒã ããŒãžãäœæãããŸãã
GitHub ããã³ Spring Security ã䜿çšããã¢ããªã±ãŒã·ã§ã³ã®ä¿è·
ã¢ããªã±ãŒã·ã§ã³ãå®å šã«ããããã«ãSpring Security ãäŸåé¢ä¿ãšããŠåçŽã«è¿œå ã§ããŸããããœãŒã·ã£ã«ããã°ã€ã³ïŒGitHub ãžã®ããªã²ãŒãïŒãè¡ããããSpring Security OAuth 2.0 Client ã¹ã¿ãŒã¿ãŒãå«ããå¿ èŠããããŸãã
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
ããã远å ããããšã§ãããã©ã«ãã§ OAuth 2.0 ã§ã¢ããªãä¿è·ããŸãã
次ã«ãGitHub ãèªèšŒãããã€ããŒãšããŠäœ¿çšããããã«ã¢ããªãæ§æããå¿ èŠããããŸãããããå®çŸããã«ã¯ã次ãå®è¡ããŸãã
æ°ãã GitHub ã¢ããªã远å ãã
ãã°ã€ã³ã« GitHub ã® OAuth 2.0 èªèšŒã·ã¹ãã ã䜿çšããã«ã¯ãæåã«æ°ãã GitHub ã¢ããªã远å ãã (è±èª) ãè¡ãå¿ èŠããããŸãã
æ°ãã OAuth ã¢ããªãéžæãããšãæ°ãã OAuth ã¢ããªã±ãŒã·ã§ã³ã®ç»é²ããŒãžã衚瀺ãããŸããã¢ããªã®ååãšèª¬æãå
¥åããŸããæ¬¡ã«ãã¢ããªã®ããŒã ããŒãžïŒãã®å Žå㯠http://localhost:8080ïŒãå
¥åããŸããæåŸã«ãèªå¯ã³ãŒã«ãã㯠URL ã http://localhost:8080/login/oauth2/code/github
ãšããŠæå®ããã¢ããªã±ãŒã·ã§ã³ã®ç»é²ãã¯ãªãã¯ããŸãã
OAuth ãªãã€ã¬ã¯ã URI ã¯ããšã³ããŠãŒã¶ãŒã®ãŠãŒã¶ãŒãšãŒãžã§ã³ãã GitHub ã§èªèšŒãããã¢ããªã±ãŒã·ã§ã³ã®æ¿èªããŒãžã§ã¢ããªã±ãŒã·ã§ã³ãžã®ã¢ã¯ã»ã¹ãèªå¯ããåŸã«ãªãã€ã¬ã¯ããããã¢ããªã±ãŒã·ã§ã³å ã®ãã¹ã§ãã
ããã©ã«ãã®ãªãã€ã¬ã¯ã URI ãã³ãã¬ãŒã㯠{baseUrl}/login/oauth2/code/{registrationId} ã§ããregistrationId ã¯ãClientRegistration ã®äžæã®èå¥åã§ãã |
application.yml
ãæ§æãã
次ã«ãGitHub ãžã®ãªã³ã¯ãäœæããã«ã¯ã以äžã application.yml
ã«è¿œå ããŸãã
spring:
security:
oauth2:
client:
registration:
github:
clientId: github-client-id
clientSecret: github-client-secret
# ...
GitHub ã§äœæããã°ããã® OAuth 2.0 è³æ Œæ
å ±ã䜿çšããgithub-client-id
ãã¯ã©ã€ã¢ã³ã ID ã«ãgithub-client-secret
ãã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ããã«çœ®ãæããã ãã§ãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãã
ãã®å€æŽã«ãããã¢ããªãå床å®è¡ã㊠http://localhost:8080 ã®ããŒã ããŒãžã«ã¢ã¯ã»ã¹ã§ããŸããããã§ãããŒã ããŒãžã®ä»£ããã«ãGitHub ã§ã®ãã°ã€ã³ã«ãªãã€ã¬ã¯ããããã¯ãã§ãããããè¡ããè¡ãããã«æ±ããããèªå¯ãåãå ¥ãããšãããŒã«ã«ã¢ããªã«ãªãã€ã¬ã¯ããããããŒã ããŒãžã衚瀺ãããŸãã
GitHub ã«ãã°ã€ã³ãããŸãŸã«ãããšãCookie ããã£ãã·ã¥ããŒã¿ã®ãªãæ°ãããã©ãŠã¶ãŒã§éããŠãããã®ããŒã«ã«ã¢ããªã§åèªèšŒããå¿ èŠã¯ãããŸããã(ãããã·ã³ã°ã«ãµã€ã³ãªã³ã®æå³ã§ãã)
ãã®ã»ã¯ã·ã§ã³ã§ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ã䜿çšããŠããå Žåã¯ããã©ãŠã¶ãŒã®ãã£ãã·ã¥ã® Cookie ãš HTTP åºæ¬èªèšŒæ å ±ãå¿ ãã¯ãªã¢ããŠãã ãããåäžã®ãµãŒããŒã§ãããè¡ãæè¯ã®æ¹æ³ã¯ãæ°ãããã©ã€ããŒããŠã£ã³ããŠãéãããšã§ãã |
äœãèµ·ãã£ãŠããã®ãïŒ
OAuth 2.0 ã®çšèªã§èšè¿°ããã¢ããªã¯ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã§ãããèªèšŒã³ãŒãä»äž [IETF] (è±èª) ã䜿çšã㊠GitHubïŒèªèšŒãµãŒããŒïŒããã¢ã¯ã»ã¹ããŒã¯ã³ãååŸããŸãã
次ã«ãã¢ã¯ã»ã¹ããŒã¯ã³ã䜿çšããŠããã°ã€ã³ ID ãååãªã©ã®å人çãªè©³çްïŒèš±å¯ããæäœã®ã¿ïŒã GitHub ã«èŠæ±ããŸãããã®ãã§ãŒãºã§ã¯ãGitHub ã¯ãªãœãŒã¹ãµãŒããŒãšããŠæ©èœããéä¿¡ããããŒã¯ã³ããã³ãŒããããŠãŒã¶ãŒã®è©³çްãžã®ã¢ã¯ã»ã¹ãã¢ããªã«èš±å¯ãããã©ããã確èªããŸãããã®ããã»ã¹ãæåãããšãã¢ããªã¯ãŠãŒã¶ãŒã®è©³çްã Spring Security ã³ã³ããã¹ãã«æ¿å ¥ããŠããŠãŒã¶ãŒãèªèšŒãããããã«ããŸãã
ãã©ãŠã¶ãŒããŒã«ïŒChrome ãŸã㯠Firefox ã® F12ïŒã調ã¹ãŠããã¹ãŠã®ãããã®ãããã¯ãŒã¯ãã©ãã£ãã¯ã远跡ãããšãGitHub ã§ååŸã«ãªãã€ã¬ã¯ãã衚瀺ãããæçµçã«æ°ãã Set-Cookie
ã§ããŒã ããŒãžã«æ»ããŸããããããŒããã® CookieïŒããã©ã«ãã§ã¯ JSESSIONID
ïŒã¯ãSpringïŒãŸãã¯ãµãŒãã¬ããããŒã¹ã®ïŒã¢ããªã±ãŒã·ã§ã³ã®èªèšŒè©³çްã®ããŒã¯ã³ã§ãã
ãŠãŒã¶ãŒãå€éšãããã€ããŒïŒGitHubïŒã§èªèšŒããå¿ èŠãããã³ã³ãã³ãã衚瀺ãããšããæå³ã§ãå®å šãªã¢ããªã±ãŒã·ã§ã³ããããŸãã
ã€ã³ã¿ãŒããããã³ãã³ã°ã® Web ãµã€ãã«ããã䜿çšããããªãã§ããããããããåºæ¬çãªèå¥ã®ç®çã®ããããµã€ãã®ç°ãªããŠãŒã¶ãŒéã§ã³ã³ãã³ããåé¢ããããã«ãåªããåºçºç¹ã§ãããã®ããããã®çš®ã®èªèšŒã¯æè¿éåžžã«äººæ°ããããŸãã
次ã®ã»ã¯ã·ã§ã³ã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã«ããã€ãã®åºæ¬çãªæ©èœã远å ããŸãããŸããGitHub ãžã®æåã®ãªãã€ã¬ã¯ããååŸãããšãã«äœãèµ·ãã£ãŠããã®ãããŠãŒã¶ãŒã«å°ãããããããããŸãã
ããããããŒãžã远å ãã
ãã®ã»ã¯ã·ã§ã³ã§ã¯ãGitHub ã§ãã°ã€ã³ããããã®æç€ºçãªãªã³ã¯ã远å ããŠãäœæããåçŽãªã¢ããªã倿ŽããŸããããã«ãªãã€ã¬ã¯ãããã代ããã«ãæ°ãããªã³ã¯ãããŒã ããŒãžã«è¡šç€ºããããŠãŒã¶ãŒã¯ãã°ã€ã³ããããèªèšŒãããªããŸãŸã«ããããéžæã§ããŸãããŠãŒã¶ãŒããªã³ã¯ãã¯ãªãã¯ããå Žåã«ã®ã¿ãå®å šãªã³ã³ãã³ããã¬ã³ããªã³ã°ãããŸãã
ããŒã ããŒãžã®æ¡ä»¶ä»ãã³ã³ãã³ã
ãŠãŒã¶ãŒãèªèšŒãããŠãããšããæ¡ä»¶ã§ã³ã³ãã³ããã¬ã³ããªã³ã°ããã«ã¯ããµãŒããŒåŽãŸãã¯ã¯ã©ã€ã¢ã³ãåŽã®ã¬ã³ããªã³ã°ã®ãªãã·ã§ã³ããããŸãã
ããã§ã¯ãJQuery (è±èª) ã䜿çšããŠã¯ã©ã€ã¢ã³ãåŽã倿ŽããŸãããä»ã®ãã®ã䜿çšããå Žåã¯ãã¯ã©ã€ã¢ã³ãã³ãŒãã倿ããã®ã¯ããã»ã©é£ãããªãã¯ãã§ãã
åçã³ã³ãã³ããéå§ããã«ã¯ã次ã®ãã㪠HTML èŠçŽ ãããã€ãããŒã¯ããå¿ èŠããããŸãã
<div class="container unauthenticated">
With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div class="container authenticated" style="display:none">
Logged in as: <span id="user"></span>
</div>
ããã©ã«ãã§ã¯ãæåã® <div>
ã衚瀺ããã2 çªç®ã® <div>
ã¯è¡šç€ºãããŸãããid
屿§ãæã€ç©ºã® <span>
ã«ã泚æããŠãã ããã
ããã«ããã°ã€ã³ãããŠãŒã¶ãŒã®è©³çްã JSON ãšããŠè¿ããµãŒããŒåŽã®ãšã³ããã€ã³ãã远å ããŸãã
ãã ããæåã«ããã®ãšã³ããã€ã³ãã«ãããããæ¬¡ã® JavaScript ã远å ããŸãããšã³ããã€ã³ãã®ã¬ã¹ãã³ã¹ã«åºã¥ããŠããã® JavaScript 㯠<span>
ã¿ã°ã«ãŠãŒã¶ãŒåãå
¥åãã<div>
ãé©åã«åãæ¿ããŸãã
<script type="text/javascript">
$.get("/user", function(data) {
$("#user").html(data.name);
$(".unauthenticated").hide()
$(".authenticated").show()
});
</script>
ãã® JavaScript ã¯ããµãŒããŒåŽã®ãšã³ããã€ã³ãã /user
ãšåŒã°ããããšãæåŸ
ããŠããããšã«æ³šæããŠãã ããã
/user
ãšã³ããã€ã³ã
ããã§ãäžèšã®ãµãŒããŒåŽã®ãšã³ããã€ã³ãã远å ããŠã/user
ãšåŒã³ãŸããçŸåšãã°ã€ã³ããŠãããŠãŒã¶ãŒãéãè¿ããŸããããã¯ãã¡ã€ã³ã¯ã©ã¹ã§éåžžã«ç°¡åã«å®è¡ã§ããŸãã
@SpringBootApplication
@RestController
public class SocialApplication {
@GetMapping("/user")
public Map<String, Object> user(@AuthenticationPrincipal OAuth2User principal) {
return Collections.singletonMap("name", principal.getAttribute("name"));
}
public static void main(String[] args) {
SpringApplication.run(SocialApplication.class, args);
}
}
ãã³ãã©ãŒã¡ãœããã«æ¿å
¥ããã @RestController
ã@GetMapping
ãOAuth2User
ã®äœ¿çšã«æ³šæããŠãã ããã
ãšã³ããã€ã³ãã« OAuth2User å
šäœãè¿ãããšã¯ããã©ãŠã¶ãŒã¯ã©ã€ã¢ã³ãã«ã¯å
¬éããããªãæ
å ±ãå«ãŸããŠããå¯èœæ§ããããããçŽ æŽãããã¢ã€ãã¢ã§ã¯ãããŸããã |
ããŒã ããŒãžãå ¬éãã
æåŸã« 1 ã€ã®å€æŽãå¿ èŠã§ãã
ããã§ããã®ã¢ããªã¯ä»¥åãšåæ§ã«æ£åžžã«æ©èœããèªèšŒãããŸãããããŒãžã衚瀺ããåã«ãªãã€ã¬ã¯ããããŸãããªã³ã¯ã衚瀺ããã«ã¯ãWebSecurityConfigurerAdapter
ãç¶æ¿ããŠããŒã ããŒãžã®ã»ãã¥ãªãã£ããªãã«ããå¿
èŠããããŸãã
@SpringBootApplication
@RestController
public class SocialApplication extends WebSecurityConfigurerAdapter {
// ...
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests(a -> a
.antMatchers("/", "/error", "/webjars/**").permitAll()
.anyRequest().authenticated()
)
.exceptionHandling(e -> e
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
)
.oauth2Login();
// @formatter:on
}
}
Spring Boot ã¯ã@SpringBootApplication
ã¢ãããŒã·ã§ã³ãä»ããããã¯ã©ã¹ã® WebSecurityConfigurerAdapter
ã«ç¹å¥ãªæå³ãä»å ããŸããããã䜿çšããŠãOAuth 2.0 èªèšŒããã»ããµãŒãéã¶ã»ãã¥ãªãã£ãã£ã«ã¿ãŒãã§ãŒã³ãæ§æããŸãã
äžèšã®æ§æã¯ãèš±å¯ããããšã³ããã€ã³ãã®ãã¯ã€ããªã¹ãã瀺ããä»ã®ãã¹ãŠã®ãšã³ããã€ã³ãã¯èªèšŒãå¿ èŠãšããŸãã
èš±å¯ããã:
/
ãããã¯åçã«äœæããããŒãžã§ããããã®ã³ã³ãã³ãã®äžéšã¯èªèšŒãããŠããªããŠãŒã¶ãŒã«ã衚瀺ãããããã§ãã/error
ãããã¯ããšã©ãŒã衚瀺ããããã® Spring Boot ãšã³ããã€ã³ã/webjars/**
ã¯ãèªèšŒãããŠãããã©ããã«ãããããããã¹ãŠã®èšªåè ã«å¯Ÿã㊠JavaScript ãå®è¡ããããã§ãã
ãã ãããã®æ§æã§ã¯ /user
ã«ã€ããŠã¯äœã衚瀺ãããŸããã/user
ãå«ããã¹ãŠã®ãã®ã¯ãæåŸã® .anyRequest().authenticated()
æ§æã®ããã«ç€ºãããªãéããå®å
šãªãŸãŸã§ãã
æåŸã«ãAjax ãä»ããŠããã¯ãšã³ããšã€ã³ã¿ãŒãã§ãŒã¹ããããããã°ã€ã³ããŒãžã«ãªãã€ã¬ã¯ãããããã©ã«ãã®åäœã§ã¯ãªãã401 ã§å¿çããããã«ãšã³ããã€ã³ããæ§æããå¿
èŠããããŸããauthenticationEntryPoint
ãæ§æããããšã§ãããå®çŸããŸãã
ãããã®å€æŽãå®äºãããšãã¢ããªã±ãŒã·ã§ã³ã宿ããŸããã¢ããªã±ãŒã·ã§ã³ãå®è¡ããŠããŒã ããŒãžã«ã¢ã¯ã»ã¹ãããšããGitHub ã§ãã°ã€ã³ããžã®é©åãªã¹ã¿ã€ã«ã® HTML ãªã³ã¯ã衚瀺ãããŸãããã®ãªã³ã¯ã¯ãGitHub ã«çŽæ¥ã§ã¯ãªããèªèšŒãåŠçããïŒããã³ GitHub ã«ãªãã€ã¬ã¯ããéä¿¡ããïŒããŒã«ã«ãã¹ã«ç§»åããŸããèªèšŒãå®äºãããšãããŒã«ã«ã¢ããªã«ãªãã€ã¬ã¯ããããååã衚瀺ãããããã«ãªããŸãïŒGitHub ã§ãã®ããŒã¿ãžã®ã¢ã¯ã»ã¹ãèš±å¯ããããã«ã¢ã¯ã»ã¹èš±å¯ãèšå®ããå ŽåïŒã
ãã°ã¢ãŠããã¿ã³ã远å ãã
ãã®ã»ã¯ã·ã§ã³ã§ã¯ããŠãŒã¶ãŒãã¢ããªãããã°ã¢ãŠãã§ãããã¿ã³ã远å ããŠãäœæããã¯ãªãã¯ã¢ããªã倿ŽããŸããããã¯åçŽãªæ©èœã®ããã«èŠããŸãããå®è£ ã«ã¯å€å°ã®æ³šæãå¿ èŠãªã®ã§ãæ£ç¢ºã«è¡ãæ¹æ³ãè°è«ããã®ã«æéãããã䟡å€ããããŸããã»ãšãã©ã®å€æŽã¯ãã¢ããªãèªã¿åãå°çšãªãœãŒã¹ããèªã¿åã / æžã蟌ã¿ãªãœãŒã¹ã«å€æããŠãããšããäºå®ã«é¢ä¿ããŠããããïŒãã°ã¢ãŠãã«ã¯ç¶æ ã®å€æŽãå¿ èŠã§ãïŒãå®éã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯åã倿Žãå¿ èŠã«ãªããŸããåãªãéçã³ã³ãã³ãã§ã¯ãããŸããã
ã¯ã©ã€ã¢ã³ãåŽã®å€æŽ
ã¯ã©ã€ã¢ã³ãã§ã¯ããã°ã¢ãŠããã¿ã³ãšããã€ãã® JavaScript ãæäŸããã ãã§ããµãŒããŒã«ã³ãŒã«ããã¯ããŠèªèšŒã®ãã£ã³ã»ã«ãèŠæ±ã§ããŸãããŸããUI ã®ãèªèšŒæžã¿ãã»ã¯ã·ã§ã³ã§ããã¿ã³ã远å ããŸãã
<div class="container authenticated"> Logged in as: <span id="user"></span> <div> <button onClick="logout()" class="btn btn-primary">Logout</button> </div> </div>
ãããŠãJavaScript ã§åç
§ãã logout()
颿°ãæäŸããŸãã
var logout = function() { $.post("/logout", function() { $("#user").html(''); $(".unauthenticated").show(); $(".authenticated").hide(); }) return true; }
logout()
颿°ã¯ /logout
ã«å¯Ÿã㊠POST ãå®è¡ããåçã³ã³ãã³ããã¯ãªã¢ããŸããããã§ããµãŒããŒåŽã«åãæ¿ããŠãã®ãšã³ããã€ã³ããå®è£
ã§ããŸãã
ãã°ã¢ãŠããšã³ããã€ã³ãã®è¿œå
Spring Security ã¯ã/logout
ãšã³ããã€ã³ãã®ãµããŒããçµã¿èŸŒãã§ããŸããããã«ãããæ£ããåŠçãè¡ãããŸãïŒã»ãã·ã§ã³ãã¯ãªã¢ããCookie ãç¡å¹ã«ããŸãïŒããšã³ããã€ã³ããæ§æããã«ã¯ãWebSecurityConfigurerAdapter
ã®æ¢åã® configure()
ã¡ãœãããåçŽã«æ¡åŒµããŸãã
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing code here
.logout(l -> l
.logoutSuccessUrl("/").permitAll()
)
// ... existing code here
// @formatter:on
}
/logout
ãšã³ããã€ã³ãã¯ãPOST ããå¿
èŠãããããŠãŒã¶ãŒãã¯ãã¹ãµã€ããªã¯ãšã¹ããã©ãŒãžã§ãªïŒCSRFããã·ãŒãµãŒãããšçºé³ïŒããä¿è·ããã«ã¯ãããŒã¯ã³ããªã¯ãšã¹ãã«å«ããå¿
èŠããããŸããããŒã¯ã³ã®å€ã¯çŸåšã®ã»ãã·ã§ã³ã«ãªã³ã¯ãããŠããããããä¿è·ãæäŸããŠãããããJavaScript ã¢ããªã«ãã®ããŒã¿ãååŸããæ¹æ³ãå¿
èŠã§ãã
å€ãã® JavaScript ãã¬ãŒã ã¯ãŒã¯ã«ã¯ CSRF ã®ãµããŒããçµã¿èŸŒãŸããŠããŸãã (ããšãã°ãAngular ã§ã¯ XSRF ãšåŒã°ããŠããŸã)ãå€ãã®å ŽåãSpring Security ã®æšæºã®åäœãšã¯å°ãç°ãªãæ¹æ³ã§å®è£ ãããŠããŸããããšãã°ãAngular ã§ã¯ãããã³ããšã³ãã¯ãµãŒããŒãã "XSRF-TOKEN" ãšãã Cookie ãéä¿¡ãããããšãæãã§ããããããæ€åºãããšããã®å€ã "X-XSRF-TOKEN" ãšããããããŒãšããŠè¿ããŸããåãåäœãã·ã³ãã«ãª jQuery ã¯ã©ã€ã¢ã³ãã§å®è£ ãããšããµãŒããŒåŽã®å€æŽã¯ã倿ŽããŸã£ããè¡ããããŸãã¯ã»ãšãã©è¡ããã«ä»ã®ããã³ããšã³ãå®è£ ã§ãæ©èœããŸããSpring Security ã«ãããæããã«ã¯ãCookie ãäœæãããã£ã«ã¿ãŒã远å ããå¿ èŠããããŸãã
WebSecurityConfigurerAdapter
ã§ã¯ã次ã®ããšãè¡ããŸãã
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing code here
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
// ... existing code here
// @formatter:on
}
ã¯ã©ã€ã¢ã³ãã« CSRF ããŒã¯ã³ã远å ãã
ãã®ãµã³ãã«ã§ã¯é«ã¬ãã«ã®ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠããªããããããã¯ãšã³ããã Cookie ãšããŠäœ¿çšå¯èœã«ãã CSRF ããŒã¯ã³ãæç€ºçã«è¿œå ããå¿
èŠããããŸããã³ãŒããå°ãåçŽã«ããããã«ãjs-cookie
ã©ã€ãã©ãªãã€ã³ã¯ã«ãŒãããŸãã
<dependency>
<groupId>org.webjars</groupId>
<artifactId>js-cookie</artifactId>
<version>2.1.0</version>
</dependency>
次ã«ãHTML ã§åç §ã§ããŸãã
<script type="text/javascript" src="/webjars/js-cookie/js.cookie.js"></script>
æåŸã«ãXHR ã§ Cookies
ã³ã³ãããšã³ã¹ã¡ãœããã䜿çšã§ããŸãã
$.ajaxSetup({
beforeSend : function(xhr, settings) {
if (settings.type == 'POST' || settings.type == 'PUT'
|| settings.type == 'DELETE') {
if (!(/^http:.*/.test(settings.url) || /^https:.*/
.test(settings.url))) {
// Only send the token to relative URLs i.e. locally.
xhr.setRequestHeader("X-XSRF-TOKEN",
Cookies.get('XSRF-TOKEN'));
}
}
}
});
æºåå®äº !
ãããã®å€æŽãå®äºããããã¢ããªãå®è¡ããŠæ°ãããã°ã¢ãŠããã¿ã³ãè©Šãæºåãã§ããŸãããã¢ããªãèµ·åããæ°ãããã©ãŠã¶ãŒãŠã£ã³ããŠã«ããŒã ããŒãžãèªã¿èŸŒã¿ãŸããããã°ã€ã³ããªã³ã¯ãã¯ãªãã¯ããŠãGitHub ã«ç§»åããŸãïŒãã§ã«ãã°ã€ã³ããŠããå Žåã¯ããªãã€ã¬ã¯ãã«æ°ä»ããªãå ŽåããããŸãïŒããã°ã¢ãŠããã¿ã³ãã¯ãªãã¯ããŠãçŸåšã®ã»ãã·ã§ã³ããã£ã³ã»ã«ããã¢ããªãèªèšŒãããŠããªãç¶æ ã«æ»ããŸããèå³ãããå Žåã¯ããã©ãŠã¶ãŒãããŒã«ã«ãµãŒããŒãšäº€æãããªã¯ãšã¹ãã§æ°ãã Cookie ãšããããŒã確èªã§ããã¯ãã§ãã
ãã°ã¢ãŠããšã³ããã€ã³ãããã©ãŠã¶ãŒã¯ã©ã€ã¢ã³ãã§åäœããããã«ãªããŸãããä»ã®ãã¹ãŠã® HTTP ãªã¯ãšã¹ãïŒPOSTãPUTãDELETE ãªã©ïŒãåæ§ã«åäœããããšãèŠããŠãããŠãã ãããããã¯ãããçŸå®çãªæ©èœãåããã¢ããªã±ãŒã·ã§ã³ã«é©ãããã©ãããã©ãŒã ã«ãªãã¯ãã§ãã
GitHub ã§ãã°ã€ã³
ãã®ã»ã¯ã·ã§ã³ã§ã¯ããã§ã«æ§ç¯ãããã°ã¢ãŠãã¢ããªã倿Žããã¹ããã«ãŒããŒãžã远å ããŠããšã³ããŠãŒã¶ãŒãè€æ°ã®è³æ Œæ å ±ã»ããããéžæã§ããããã«ããŸãã
ãšã³ããŠãŒã¶ãŒã® 2 çªç®ã®ãªãã·ã§ã³ãšã㊠Google ã远å ããŸãããã
åæèšå®
ãã°ã€ã³ã« Google ã® OAuth 2.0 èªèšŒã·ã¹ãã ã䜿çšããã«ã¯ãGoogle API ã³ã³ãœãŒã«ã§ãããžã§ã¯ããèšå®ããOAuth 2.0 è³æ Œæ å ±ãååŸããå¿ èŠããããŸãã
èªèšŒçšã® Google ã® OAuth 2.0 å®è£ (è±èª) 㯠OpenID Connect 1.0 (è±èª) 仿§ã«æºæ ããŠãããOpenID èªå® (è±èª) ã§ãã |
ãOAuth 2.0 ã®ã»ããã¢ãããã»ã¯ã·ã§ã³ããå§ãŸã OpenID Connect (è±èª) ããŒãžã®æç€ºã«åŸã£ãŠãã ããã
ãOAuth 2.0 è³æ Œæ å ±ã®ååŸãã®æé ãå®äºãããšãã¯ã©ã€ã¢ã³ã ID ãšã¯ã©ã€ã¢ã³ãã·ãŒã¯ã¬ããã§æ§æãããè³æ Œæ å ±ãæã€æ°ãã OAuth ã¯ã©ã€ã¢ã³ããå¿ èŠã«ãªããŸãã
ãªãã€ã¬ã¯ã URI ã®èšå®
ãŸãã以åã« GitHub ã«å¯ŸããŠè¡ã£ãããã«ããªãã€ã¬ã¯ã URI ãæäŸããå¿ èŠããããŸãã
ããªãã€ã¬ã¯ã URI ã®èšå®ããµãã»ã¯ã·ã§ã³ã§ãæ¿èªããããªãã€ã¬ã¯ã URI ãã£ãŒã«ãã http://localhost:8080/login/oauth2/code/google
ã«èšå®ãããŠããããšã確èªããŸãã
ã¯ã©ã€ã¢ã³ãç»é²ã®è¿œå
次ã«ãGoogle ãæãããã«ã¯ã©ã€ã¢ã³ããæ§æããå¿ èŠããããŸããSpring Security ã¯è€æ°ã®ã¯ã©ã€ã¢ã³ãã念é ã«çœ®ããŠæ§ç¯ãããŠãããããGitHub çšã«äœæããè³æ Œæ å ±ãšäžŠè¡ã㊠Google è³æ Œæ å ±ã远å ã§ããŸãã
spring:
security:
oauth2:
client:
registration:
github:
clientId: github-client-id
clientSecret: github-client-secret
google:
client-id: google-client-id
client-secret: google-client-secret
ã芧ã®ãšãããGoogle ã¯ãSpring Security ãããã«äœ¿çšã§ãããµããŒããæäŸãããã 1 ã€ã®ãããã€ããŒã§ãã
ãã°ã€ã³ãªã³ã¯ã®è¿œå
ã¯ã©ã€ã¢ã³ãã§ã¯ã倿Žã¯ç°¡åã§ã - å¥ã®ãªã³ã¯ã远å ããã ãã§ã:
<div class="container unauthenticated">
<div>
With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div>
With Google: <a href="/oauth2/authorization/google">click here</a>
</div>
</div>
URL ã®æçµãã¹ã¯ãapplication.yml ã®ã¯ã©ã€ã¢ã³ãç»é² ID ãšäžèŽããå¿
èŠããããŸãã |
Spring Security ã«ã¯ã/oauth2/authorization/{registrationId} ã§ã¯ãªã /login ããã€ã³ãããããšã§ã¢ã¯ã»ã¹ã§ããããã©ã«ãã®ãããã€ããŒéžæããŒãžãä»å±ããŠããŸãã |
ããŒã«ã«ãŠãŒã¶ãŒããŒã¿ããŒã¹ã远å ããæ¹æ³
å€ãã®ã¢ããªã±ãŒã·ã§ã³ã¯ãèªèšŒãå€éšãããã€ããŒã«å§è²ãããŠããå Žåã§ãããŠãŒã¶ãŒã«é¢ããããŒã¿ãããŒã«ã«ã«ä¿æããå¿ èŠããããŸããããã§ã¯ã³ãŒãã瀺ããŠããŸãããã2 ã€ã®ã¹ãããã§ç°¡åã«å®è¡ã§ããŸãã
ããŒã¿ããŒã¹ã®ããã¯ãšã³ããéžæããããŒãºã«åã£ãã«ã¹ã¿ã
User
ãªããžã§ã¯ãã®ãªããžããªïŒããšãã° Spring Data ã䜿çšïŒãã»ããã¢ããããå€éšèªèšŒããå®å šãŸãã¯éšåçã«ããŒã¿ãåã蟌ãããšãã§ããŸããOAuth2UserService
ãå®è£ ããŠå ¬éããããŒã¿ããŒã¹ãšåæ§ã«èªå¯ãµãŒããŒãåŒã³åºããŸããå®è£ ã¯ããã©ã«ãã®å®è£ ã«å§è²ã§ããŸããããã«ãããèªå¯ãµãŒããŒãåŒã³åºããšããæéãããããŸããå®è£ ã¯ãã«ã¹ã¿ãUser
ãªããžã§ã¯ããç¶æ¿ããOAuth2User
ãå®è£ ãããã®ãè¿ãå¿ èŠããããŸãã
ãã³ã: User
ãªããžã§ã¯ãã«ãã£ãŒã«ãã远å ããŠãå€éšãããã€ããŒã®äžæã®èå¥åã«ãªã³ã¯ããŸãïŒãŠãŒã¶ãŒã®ååã§ã¯ãªããå€éšãããã€ããŒã®ã¢ã«ãŠã³ãã«åºæã®ãã®ïŒã
èªèšŒãããŠããªããŠãŒã¶ãŒçšã®ãšã©ãŒããŒãžã®è¿œå
ãã®ã»ã¯ã·ã§ã³ã§ã¯ã以åã«äœæãã 2 ã€ã®ãããã€ããŒã¢ããªã倿ŽããŠãèªèšŒã§ããªããŠãŒã¶ãŒã«ãã£ãŒãããã¯ãæäŸããŸããåæã«ãèªèšŒããžãã¯ãç¶æ¿ããŠããŠãŒã¶ãŒãç¹å®ã® GitHub çµç¹ã«å±ããŠããå Žåã«ã®ã¿ãŠãŒã¶ãŒãèš±å¯ããã«ãŒã«ãå«ããŸãããçµç¹ã㯠GitHub ãã¡ã€ã³åºæã®æŠå¿µã§ãããåæ§ã®ã«ãŒã«ãä»ã®ãããã€ããŒã«ãèæ¡ãããå¯èœæ§ããããŸããäŸ: Google ã§ã¯ãç¹å®ã®ãã¡ã€ã³ã®ãŠãŒã¶ãŒã®ã¿ãèªèšŒãããå ŽåããããŸãã
GitHub ãžã®åãæ¿ã
2 ãããã€ããŒã®ãµã³ãã«ã§ã¯ãGitHub ã OAuth 2.0 ãããã€ããŒãšããŠäœ¿çšããŠããŸãã
spring:
security:
oauth2:
client:
registration:
github:
client-id: bd1c0a783ccdd1c9b9e4
client-secret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
# ...
ã¯ã©ã€ã¢ã³ãã§ã®èªèšŒå€±æã®æ€åº
ã¯ã©ã€ã¢ã³ãã§ã¯ãèªèšŒã§ããªãã£ããŠãŒã¶ãŒã«ãã£ãŒãããã¯ãæäŸããããšãã§ããŸããããã容æã«ããããã«ãæçµçã«æ å ±ã¡ãã»ãŒãžã远å ãã div ã远å ã§ããŸãã
<div class="container text-danger error"></div>
次ã«ã/error
ãšã³ããã€ã³ãã«åŒã³åºãã远å ãã<div>
ã«çµæãå
¥åããŸãã
$.get("/error", function(data) { if (data) { $(".error").html(data); } else { $(".error").html(''); } });
ãšã©ãŒé¢æ°ã¯ã衚瀺ãããšã©ãŒããããã©ãããããã¯ãšã³ãã§ç¢ºèªããŸã
ãšã©ãŒã¡ãã»ãŒãžã远å ãã
ãšã©ãŒã¡ãã»ãŒãžã®ååŸããµããŒãããã«ã¯ãèªèšŒã倱æãããšãã«ãã£ããã£ãŒããå¿
èŠããããŸãããããå®çŸããããã«ã次ã®ããã« AuthenticationFailureHandler
ãæ§æã§ããŸãã
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// ... existing configuration
.oauth2Login(o -> o
.failureHandler((request, response, exception) -> {
request.getSession().setAttribute("error.message", exception.getMessage());
handler.onAuthenticationFailure(request, response, exception);
})
);
}
äžèšã¯ãèªèšŒã倱æãããã³ã«ãšã©ãŒã¡ãã»ãŒãžãã»ãã·ã§ã³ã«ä¿åããŸãã
次ã«ã次ã®ãããªåçŽãª /error
ã³ã³ãããŒã©ãŒã远å ã§ããŸãã
@GetMapping("/error")
public String error(HttpServletRequest request) {
String message = (String) request.getSession().getAttribute("error.message");
request.getSession().removeAttribute("error.message");
return message;
}
ããã«ãããã¢ããªã®ããã©ã«ãã® /error ããŒãžã眮ãæããããŸããããã¯ããã®ã±ãŒã¹ã§ã¯åé¡ãããŸããããããŒãºã«åãããŠååã«æŽç·ŽãããŠããªãå ŽåããããŸãã |
ãµãŒããŒã§ 401 ãçæãã
ãŠãŒã¶ãŒã GitHub ã§ãã°ã€ã³ã§ããªãããŸãã¯ãã°ã€ã³ããããªãå Žåã¯ãSpring Security ãã 401 ã¬ã¹ãã³ã¹ããã§ã«éä¿¡ããããããèªèšŒã«å€±æããå ŽåïŒããŒã¯ã³ã®ä»äžãæåŠãããªã©ïŒãã¢ããªã¯ãã§ã«åäœããŠããŸãã
å°ãç©äºãçãäžããããã«ãé©åãªçµç¹ã«ããªããŠãŒã¶ãŒãæåŠããããã«èªèšŒã«ãŒã«ãç¶æ¿ã§ããŸãã
GitHub API ã䜿çšããŠãŠãŒã¶ãŒã®è©³çްã調ã¹ãããšãã§ãããããèªèšŒããã»ã¹ã®é©åãªéšåã«ãã©ã°ã€ã³ããã ãã§ãã
幞ããSpring Boot ã¯ãã®ãããªåçŽãªäœ¿çšäŸã®ããã«ãç°¡åãªæ¡åŒµãã€ã³ããæäŸããŠããŸããå OAuth2UserService
ã® @Bean
ã宣èšãããšããŠãŒã¶ãŒããªã³ã·ãã«ãèå¥ããããã«äœ¿çšãããŸãããã®ããã¯ã䜿çšããŠããŠãŒã¶ãŒãæ£ããçµç¹ã«ããããšãã¢ãµãŒãããããã§ãªãå Žåã¯äŸå€ãã¹ããŒã§ããŸãã
@Bean
public OAuth2UserService<OAuth2UserRequest, OAuth2User> oauth2UserService(WebClient rest) {
DefaultOAuth2UserService delegate = new DefaultOAuth2UserService();
return request -> {
OAuth2User user = delegate.loadUser(request);
if (!"github".equals(request.getClientRegistration().getRegistrationId())) {
return user;
}
OAuth2AuthorizedClient client = new OAuth2AuthorizedClient
(request.getClientRegistration(), user.getName(), request.getAccessToken());
String url = user.getAttribute("organizations_url");
List<Map<String, Object>> orgs = rest
.get().uri(url)
.attributes(oauth2AuthorizedClient(client))
.retrieve()
.bodyToMono(List.class)
.block();
if (orgs.stream().anyMatch(org -> "spring-projects".equals(org.get("login")))) {
return user;
}
throw new OAuth2AuthenticationException(new OAuth2Error("invalid_token", "Not in Spring Team", ""));
};
}
ãã®ã³ãŒãã¯ãèªèšŒããããŠãŒã¶ãŒã«ä»£ãã£ãŠ GitHub API ã«ã¢ã¯ã»ã¹ããããã® WebClient
ã€ã³ã¹ã¿ã³ã¹ã«äŸåããŠããããšã«æ³šæããŠãã ããããããå®äºãããšãçµç¹ãã«ãŒãããŠã"spring-projects" ïŒãã㯠Spring ãªãŒãã³ãœãŒã¹ãããžã§ã¯ããæ ŒçŽããããã«äœ¿çšãããçµç¹ïŒã«äžèŽããçµç¹ãæ¢ããŸããæ£åžžã«èªèšŒã§ããããã«ãããããSpring ãšã³ãžãã¢ãªã³ã°ããŒã ã«æå±ããŠããªãå Žåã¯ãããã§ç¬èªã®å€ã«çœ®ãæããããšãã§ããŸããäžèŽãããã®ããªãå Žåã¯ãOAuth2AuthenticationException
ãã¹ããŒãããããã Spring Security ã«ãã£ãŠååŸããã401 ã¬ã¹ãã³ã¹ã«ãªããŸãã
WebClient
ã Bean ãšããŠäœæããå¿
èŠããããŸãããspring-boot-starter-oauth2-client
ã䜿çšããããšã§ãã®æåããã¹ãŠèªåã§æžã蟌ãããããç°¡åã§ãã
@Bean
public WebClient rest(ClientRegistrationRepository clients, OAuth2AuthorizedClientRepository authz) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(clients, authz);
return WebClient.builder()
.filter(oauth2).build();
}
æããã«ãäžèšã®ã³ãŒãã¯ä»ã®èªèšŒã«ãŒã«ã«äžè¬åã§ããäžéšã¯ GitHub ã«ãäžéšã¯ä»ã® OAuth 2.0 ãããã€ããŒã«é©çšã§ããŸããå¿
èŠãªã®ã¯ãWebClient ãšãããã€ããŒã® API ã®ç¥èã ãã§ãã |
çµè«
Spring Boot ãš Spring Security ã䜿çšããŠãéåžžã«å°ãªãåŽåã§å€ãã®ã¹ã¿ã€ã«ã®ã¢ããªãæ§ç¯ããæ¹æ³ãèŠãŠããŸããããã¹ãŠã®ãµã³ãã«ã§å®è¡ãããã¡ã€ã³ããŒãã¯ãå€éš OAuth 2.0 ãããã€ããŒã䜿çšããèªèšŒã§ãã
ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ã¯ãã¹ãŠãéåžžã¯æ§æãã¡ã€ã«ã倿Žããã ãã§ãããå ·äœçãªãŠãŒã¹ã±ãŒã¹ã«åãããŠç°¡åã«æ¡åŒµããã³åæ§æã§ããŸããç¬èªã®ãµãŒããŒã§ãµã³ãã«ã®ããŒãžã§ã³ã䜿çšã㊠GitHubïŒãŸãã¯åæ§ã®ïŒã«ç»é²ããç¬èªã®ãã¹ãã¢ãã¬ã¹ã®ã¯ã©ã€ã¢ã³ãè³æ Œæ å ±ãååŸããå Žåã¯èŠããŠãããŠãã ããããããŠããããã®è³æ Œæ å ±ããœãŒã¹ç®¡çã«å ¥ããªãããšãå¿ããªãã§ãã ããïŒ
æ°ããã¬ã€ããäœæããããæ¢åã®ã¬ã€ãã«è²¢ç®ãããã§ããïŒ æçš¿ã¬ã€ãã©ã€ã³ãåç §ããŠãã ãã [GitHub] (è±èª) ã
ãã¹ãŠã®ã¬ã€ãã¯ãã³ãŒãçšã® ASLv2 ã©ã€ã»ã³ã¹ãããã³ããã¥ã¡ã³ãçšã® AttributionãNoDerivatives creative commons ã©ã€ã»ã³ã¹ (è±èª) ã§ãªãªãŒã¹ãããŠããŸãã |