(此處省略2000字廢話),第一次寫博客,直接進入正題了。java
從初學者的角度來看,初次使用spring-boot和spring-security-oauth2整合,第一步天然是搭建一個「Hello World」先跑起來。那麼二話不說,先來一個spring-boot的「Hello World」。web
本小菜使用idea+maven搭建項目,假設已經有了一個基本的maven-archetype-web架構,如圖:spring
關於架構的目錄結構,每一個人都有本身的見解,小菜的設計思路是client發送請求,按照「web」-「service」-「dao」的順序與數據庫交互,生成「po」。框架的配置放在「config」中,一些dao層或者其餘層的封裝放在「common」中,String、Excel等工具類放在util中,「api」是提供給外部訪問的接口層,能夠調用「service」,也能夠調用「web」。數據庫
1、搭建一個spring-boot的web項目。json
一、添加jar包:api
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.0.RELEASE</version>
</parent>
spring-boot基於spring-mvc,所以還須要瀏覽器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
如圖:
依賴成功後,在External Libraies中會顯示須要的jar包,接下來的快速簡單web開發就是靠他們了。spring-mvc
二、spring-boot啓動類安全
主要是配置@SpringBootApplication,大概意思就是告訴spring-boot程序入口在這裏。
三、"web"訪問層Controller類
四、啓動spring-boot服務器
能夠直接從App.class的main方法run或者debug啓動,也可使用mvn spring-boot:run命令啓動
輸入http://localhost:8080/home,測試結果:
2、spring-security-oauth2基本使用
通過上面的步驟,相信和本菜同樣的小菜鳥多少熟悉了idea&maven的使用。接下來是使用spring-security-oauth2保護接口的安全。
一、導入依賴jar包
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
引入後啓動項目,觀察控制檯,大概意思就是spring-security-oauth2給spring-mvc增長了一些Filter,由於都是出自於spring家族,咱們不須要關心他們內部怎麼實現,以及會不會有bug,咱們關心的是如何去使用,更深點的是出了問題如何解決以及性能方面的考慮。本菜水平有限,此處只能列出使用。
那麼繼續訪問http://localhost:8080/home,發現須要輸入用戶名、密碼,默認用戶名user,密碼會打印在控制檯。
大功告成,spring-security-oauth2起做用了...
好吧,這只是開始,那麼它是如何起的做用呢?
此處意思大概就是使用了「Basic」模式,後面是驗證信息,本菜大膽猜想是用戶名密碼。固然官方說這是不安全的,很容易被其餘人模擬瀏覽器請求,例如curl和httpClient。
爲了方便以後調試,將服務器端口號設置爲9999,設置登陸密碼。resources目錄下新增application.yml文件,內容:
spring:
application:
name: oauth2_test
server:
port: 9999
management:
context_path: /
security:
user:
password: 123123
logging:
level:
# org.springframework.security: DEBUG
重啓server,登陸名和密碼變爲user 123123
二、配置受權服務的類型
受權類型主要有
authorization_code:受權碼類型
implicit:隱式受權類型
password:資源全部者(即用戶)密碼類型
client_credentials:客戶端憑據(客戶端ID以及Key)類型
refresh_token:經過以上受權得到的刷新令牌來獲取新的令牌
這裏不考慮第二、4種受權類型。受權方法能夠經過實現「AuthorizationServerConfigurer」接口或者繼承「AuthorizationServerConfigurerAdapter」類,重寫configure方法實現。
簡單介紹spring-security-oauth2的實現機制主要是經過token,客戶端發送請求時附上服務端給的token信息,若是驗證正確則經過,authorization_code在獲取token以前須要「第三方」認證,假設第三方提供給客戶端一個受權碼,客戶端便可以拿着「第三方」給的受權碼去服務器請求token。請求時須要一些參數,主要以下:
clientId:(必輸)用來標識客戶的Id
secret:(可選)客戶端安全碼,若是有的話
scope:用來限制客戶端的訪問範圍,若是爲空(默認)的話,那麼客戶端擁有所有的訪問範圍
authorizedGrantTypes:此客戶端可使用的受權類型,默認爲空
authorities:此客戶端可使用的權限(基於Spring Security authorities)
對應的請求中默認參數名分別爲client_id、secret、scope、grant_type、不須要。
配置示例代碼:
package com.pch.web;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.security.Principal;
/**
* Created by Administrator on 2016/12/4.
*/
@RestController
public class UserController {
@RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
}
package com.pch.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* Created by Administrator on 2016/12/4.
*/
@Configuration
@EnableResourceServer
public class CustomResouceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.tokenStore(tokenStore)
// .resourceId("resourceId")
;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/home")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/user")
.access("#oauth2.hasScope('read')")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
;
}
}
package com.pch.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
/**
* Created by Administrator on 2016/12/4.
*/
@Configuration
@EnableResourceServer
public class CustomResouceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
.tokenStore(tokenStore)
// .resourceId("resourceId")
;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeRequests()
.antMatchers("/home")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/user")
.access("#oauth2.hasScope('read')")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
;
}
}
這裏不示例「authorization_code」方式認證
假設可使用「CURL」命令,使用password方式認證命令:
curl -X POST client_id:@localhost:9999/oauth/token -d "grant_type=password" -d "client_id=client_id" -d "username=user" -d "password=123123"
將返回示例json:
{"access_token":"ea3595d6-e4c5-41d7-a6c8-f2e618f751a4","token_type":"bearer","refresh_token":"7792fdc7-53af-4bf5-8741-16ba9477db44","expires_in":2839,"scope":"read write"}
curl localhost:9999/home -H "Authorization: ${token_type} ${access_token}"