OAuth 2.0是用于授權(quán)的行業(yè)標準協(xié)議。OAuth 2.0取代了在2006年創(chuàng)建的原始OAuth協(xié)議上所做的工作并级。OAuth 2.0專注于客戶端開發(fā)人員的簡單性,同時為Web應(yīng)用程序届良,桌面應(yīng)用程序竟贯,手機和客廳設(shè)備提供特定的授權(quán)流程。
開發(fā)工具:Idea
開發(fā)環(huán)境:jdk1.8 甩栈、maven3.5.0
springboot 2.1.3
1泻仙、點擊【Create New Project】創(chuàng)建一個新的項目
選擇【Spring Initializr】選擇JDK1.8,然后點擊Next
接下來填好對應(yīng)的資料量没,點擊Next:
然后選擇Springboot2.1.3,然后勾選:
接下來點擊Next
點擊Finish開始項目的編寫
我們開始一個項目的時候玉转,首先要一步一步的去配置,不能一下盲目的去配置一大堆東西后去運行殴蹄,這樣如果出錯了就很難排錯究抓,我們一步步去配置所要的框架然后去運行沒問題了再去配置下一個。
我們先是安裝Thymeleaf
加入依賴:
<dependency>
? ? <groupId>org.springframework.boot</groupId>
? ? <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
然后去resources目錄下面新建配置文件:application.yml
然后開始配置thymeleaf:
server:
? port: 8888
#thymeleaf
spring:
? thymeleaf:
? ? prefix: classpath:/templates/
? ? suffix: .html
? ? cache: false
? ? encoding: UTF-8
? ? mode: LEAGCYHTML5
? ? servlet:
? ? ? content-type: text/html
然后我們再去創(chuàng)建Controller包和ApiController.class類去編寫跳轉(zhuǎn)
package com.oauth2.pan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
/**
* @Author: Caiden(張志鑫)
* @Date: 2019/2/26 15:18
* @Version 0.0.1
*/
@Controller
@RequestMapping("/api")
public class ApiController {
? ? @RequestMapping("/hello")
? ? public ModelAndView sayHelloWorld(ModelAndView model){
? ? ? ? model.setViewName("index");
? ? ? ? return model;
? ? }
}
然后在resources -> templates 目錄下新建一個html文件:index.html袭灯。啟動運行測試:
可以訪問刺下,說明我們thymeleaf框架搭建好了。
此刻我們的目錄結(jié)構(gòu):
接下來搭建我們的oauth2認證稽荧,我們加入兩個依賴包
<dependency>
? ? <groupId>org.springframework.boot</groupId>
? ? <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
? ? <groupId>org.springframework.security.oauth</groupId>
? ? <artifactId>spring-security-oauth2</artifactId>
? ? <version>2.1.3.RELEASE</version>
</dependency>
需要注意的問題一:
1橘茉、當我們加入依賴包后可以在項目的External Libraries看下jar包是不是已經(jīng)被加入到項目里面,有些時候Jar已經(jīng)通過Maven下載完成,但是沒有導入進來捺癞。
2夷蚊、打開File->Project Structure -》Project Settings -> Libraries 中看oauth2的jar包是否有加載進來,如果下圖中綠色框框中是紅色髓介,請確保MAVEN下載JAR包成功的情況下惕鼓,刪除classes中的信息,再點擊綠色框上邊最左邊的“+”號唐础,選擇MAVEN下載好的jar包即可
當上面提到的兩個依賴jar包確認下載并加載成功后箱歧,開始進行認證編碼:
WebSecurityConfigurerAdapter是默認情況下Spring security的http配置;ResourceServerConfigurerAdapter是默認情況下spring security oauth 的http配置一膨。
(WebSecurityConfigurerAdapter的配置攔截要優(yōu)先于ResourceServerConfigurerAdapter呀邢,優(yōu)先級高的http配置是可以覆蓋優(yōu)先級低的配置的)
先覆寫spring Security的http配置
新建類名:WebSecurityConfiguration 然后去繼承 WebSecurityConfigurerAdapter
老司機避坑指南:解決 There is no PasswordEncoder mapped for the id "null")
SpringBoot升級到了2.0之后的版本,Security也由原來的版本4升級到了5
升到5版本之后的security必須加入密碼加密
WebSecurityConfiguration.class
package com.oauth2.pan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @Author: Caiden(張志鑫)
* @Date: 2019/2/26 15:57
* @Version 0.0.1
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
? ? @Override
? ? protected void configure(HttpSecurity http) throws Exception {
? ? ? ? http.csrf().disable();
? ? ? ? http.requestMatchers().antMatchers("/oauth/**","/login/**","/logout/**")
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? .authorizeRequests()
? ? ? ? ? ? ? ? .antMatchers("/oauth/**").authenticated()
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? .formLogin().permitAll();
? ? }
? ? @Override
? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception {
? ? ? ? BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
? ? ? ? auth.inMemoryAuthentication().passwordEncoder(encoder)
? ? ? ? ? ? ? ? .withUser("admin")
? ? ? ? ? ? ? ? .password(encoder.encode("admin1234")).roles("USER");
? ? }
? ? /**
? ? * 需要配置這個支持password模式
? ? */
? ? @Override
? ? @Bean
? ? public AuthenticationManager authenticationManagerBean() throws Exception {
? ? ? ? return super.authenticationManagerBean();
? ? }
? ? /**
? ? * 密碼加密
? ? * */
? ? @Bean
? ? public PasswordEncoder passwordEncoder() {
? ? ? ? return new BCryptPasswordEncoder();
? ? }
}
再去覆寫Oauth2的http配置類
ResourceServerConfig.class
package com.oauth2.pan.config.oauth2;
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;
/**
* @Author: Caiden(張志鑫)
* @Date: 2019/2/26 16:07
* @Version 0.0.1
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
? ? private static final String PAN_RESOURCE_ID = "*";
? ? @Override
? ? public void configure(HttpSecurity http) throws Exception {
? ? ? ? http.requestMatchers().antMatchers("/api/**")
? ? ? ? ? ? ? ? .and()
? ? ? ? ? ? ? ? .authorizeRequests()
? ? ? ? ? ? ? ? .antMatchers("/api/**").authenticated();
? ? }
? ? @Override
? ? public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
? ? ? ? resources.resourceId(PAN_RESOURCE_ID);
? ? }
}
再去新建一個認證服務(wù)器:
AuthorizationServerConfiguration.class
package com.oauth2.pan.config.oauth2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
/**
* @Author: Caiden(張志鑫)
* @Date: 2019/2/26 16:10
* @Version 0.0.1
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration? extends AuthorizationServerConfigurerAdapter {
? ? @Autowired
? ? private TokenStore tokenStore;
? ? @Autowired
? ? private AuthenticationManager authenticationManager;
? ? @Override
? ? public void configure(AuthorizationServerSecurityConfigurer security)throws Exception {
? ? ? ? security.allowFormAuthenticationForClients();
? ? }
? ? @Override
? ? public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
? ? ? ? BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
? ? ? ? //添加客戶端信息
? ? ? ? //使用內(nèi)存存儲OAuth客戶端信息
? ? ? ? clients.inMemory()
? ? ? ? ? ? ? ? // client_id
? ? ? ? ? ? ? ? .withClient("test")
? ? ? ? ? ? ? ? // 該client允許的授權(quán)類型豹绪,不同的類型价淌,則獲得token的方式不一樣。
? ? ? ? ? ? ? ? .authorizedGrantTypes("password")
? ? ? ? ? ? ? ? // client_secret
? ? ? ? ? ? ? ? .secret(encoder.encode("123456"))
? ? ? ? ? ? ? ? .resourceIds("*")
? ? ? ? ? ? ? ? // 允許的授權(quán)范圍
? ? ? ? ? ? ? ? .scopes("all")
? ? ? ? ? ? ? ? .accessTokenValiditySeconds(1000) //token過期時間
? ? ? ? ? ? ? ? .refreshTokenValiditySeconds(1000); //refresh過期時間;
? ? }
? ? @Override
? ? public void configure(AuthorizationServerEndpointsConfigurer endpoints)throws Exception {
? ? ? ? //reuseRefreshTokens設(shè)置為false時瞒津,每次通過refresh_token獲得access_token時蝉衣,也會刷新refresh_token;也就是說巷蚪,會返回全新的access_token與refresh_token病毡。
? ? ? ? //默認值是true,只返回新的access_token屁柏,refresh_token不變啦膜。
? ? ? ? endpoints.tokenStore(tokenStore)
? ? ? ? ? ? ? ? .authenticationManager(authenticationManager);
? ? }
? ? @Bean
? ? public TokenStore tokenStore() {
? ? ? ? //token保存在內(nèi)存中(也可以保存在數(shù)據(jù)庫、Redis中)淌喻。
? ? ? ? //如果保存在中間件(數(shù)據(jù)庫僧家、Redis),那么資源服務(wù)器與認證服務(wù)器可以不在同一個工程中似嗤。
? ? ? ? //注意:如果不保存access_token啸臀,則沒法通過access_token取得用戶信息
? ? ? ? return new InMemoryTokenStore();
? ? }
}
好了届宠,都配置好了烁落,萬事OK,快去測試一下吧豌注。
關(guān)于分享有何疑問與建議歡迎留言哦伤塌!
如果你對Spring有興趣,實訓邦精心準備了Spring2.0的深度技術(shù)講解轧铁。
可以通過鏈接學習更多SpringBoot+Vue前后端分離的內(nèi)容每聪。