爬了兩天的坑終於上來了,看別人寫的很簡單,本身寫的時候就各類問題,網上SSO文章不少,寫的時候就各類問題(本身太菜了)。記錄一下,之後方便查看。html
關於OAuth2認證和受權服務器見上一篇java
https://zheyday.github.io/2019/10/07/SpringCloud-OAuth2%E5%92%8CJWT/git
<font color=#0099ff>項目地址</font>:github
https://github.com/zheyday/SpringCloudStudy 使用git工具算法
git checkout sso
參考資料:spring
http://www.javashuo.com/article/p-cniijmfd-p.html瀏覽器
阮一峯OAuth2講解 http://www.javashuo.com/article/p-cvinqsjv-ma.html服務器
英文全稱single Sign On,中文名單點登陸。就是在多應用系統中,用戶只須要登陸一次就能夠訪問全部信任服務。SSO經過將用戶登錄信息映射到瀏覽器cookie中,解決其餘服務免登錄獲取用戶session的問題。cookie
項目中一個有5個模塊:session
oauth-server是認證和受權服務,負責令牌的發放
zuul是網關服務,實現統一受權
eureka-client和eureka-client1是兩個應用服務
eureka-server-single是eureka註冊中心
要實現的功能就是經過zuul端口訪問eureka-client,首次須要登陸,而後內部跳轉到oauth-server中進行認證和受權,成功以後也能夠不用登陸訪問eureka-client1。
詳見
https://zheyday.github.io/2019/10/07/SpringCloud-OAuth2%E5%92%8CJWT/
更改了幾個地方
@Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("zuul") .secret(new BCryptPasswordEncoder().encode("secret")) .scopes("app") .authorizedGrantTypes("authorization_code", "password") .redirectUris("http://localhost:9110/login") ; // clients.withClientDetails(new JdbcClientDetailsService(dataSource)); }
這個函數能夠爲其餘模塊資源服務器提供校驗
@RestController @RequestMapping("/oauth2_token") public class UserController { @GetMapping("/current") public Principal user(Principal principal) { return principal; } }
@Override public void configure(HttpSecurity http) throws Exception { http // antMatcher表示只能處理/oauth2_token的請求 .antMatcher("/oauth2_token/**") .authorizeRequests() .anyRequest().authenticated() ; }
添加了根地址,也就是每次訪問這個服務都要加上 /oauth-server
server: port: 9120 # url根地址 不配置的話會報invalid_token錯誤 # 或者在zuul中配置也能夠 servlet: context-path: /oauth-server
zuul做爲系統的入口,提供路由、統一受權等功能。
依賴見項目中
<font color='red'>注意:全部模塊都引入了spring-cloud-starter-oauth2依賴,因此放入了項目的公共pom.xml中,實現oauth2只須要引用這一個就能夠</font>
貼出主要配置,詳細見項目中
sensitiveHeaders:
這個必需要。zuul在轉發路由時,會改寫request中的頭部信息,設置成空就是不過濾
security.oauth2.resource:這個是和解析令牌相關的配置
資源服務器須要解析令牌驗證正確性,方式有三種:
zuul: routes: eureka-client: path: /eureka-client/** sensitiveHeaders: serviceId: eureka-client eureka-client1: path: /eureka-client1/** sensitiveHeaders: serviceId: eureka-client1 oauth-server: path: /oauth-server/** sensitiveHeaders: serviceId: eureka-client #認證服務器地址 oauth-server: http://localhost:9120/oauth-server security: oauth2: # 和認證服務器中的client設置對應 client: client-id: zuul client-secret: secret # 獲取令牌地址 access-token-uri: ${oauth-server}/oauth/token # 認證地址 user-authorization-uri: ${oauth-server}/oauth/authorize resource: # 進行令牌校驗 # 1、訪問controller獲取Principal # user-info-uri: ${oauth-server}/oauth2_token/current # prefer-token-info: false # 2、訪問受權服務器獲取公鑰 解析令牌 jwt: key-uri: ${oauth-server}/oauth/token_key
整個zuul模塊只要添加這一個配置就能夠
@EnableOAuth2Sso @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http //須要受權的url .authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and().csrf().disable() ; } }
新添以下,用於驗證請求的令牌是否正確
security: oauth2: resource: id: eureka-client # 資源服務器三種驗證令牌方法 # 1、在ResourceServerConfig中本地配置 # 2、從認證服務器獲取用戶信息 解析出token # user-info-uri: ${oauth-server}/oauth2_token/current # prefer-token-info: false # 3、遠程獲取公鑰 解析token jwt: key-uri: ${oauth-server}/oauth/token_key
資源服務器只須要添加這一個配置便可
@Configuration @EnableResourceServer //Spring Security默認禁用註解 這裏開啓註解 // 結合@PreAuthorize("hasRole('admin')")用來判斷用戶對某個控制層的方法是否有訪問權限 @EnableGlobalMethodSecurity(prePostEnabled = true) public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http // 配置須要權限的url .authorizeRequests() .anyRequest().authenticated() .and().csrf().disable(); ; } //如下就是驗證令牌的本地方法 若是使用這種,將上述application.yml的配置註釋掉,同時將oauth2.jks放入resources文件夾 // @Override // public void configure(ResourceServerSecurityConfigurer resources) throws Exception { // resources.resourceId("app").tokenStore(tokenStore()); // } // // @Bean // public TokenStore tokenStore() { // return new JwtTokenStore(jwtAccessTokenConverter()); // } // // /** // * 非對稱加密算法對token進行簽名 // * // * @return // */ // @Bean // public JwtAccessTokenConverter jwtAccessTokenConverter() { // final JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); // // 導入證書 // KeyStoreKeyFactory keyStoreKeyFactory = // new KeyStoreKeyFactory(new ClassPathResource("oauth2.jks"), "mypass".toCharArray()); // converter.setKeyPair(keyStoreKeyFactory.getKeyPair("oauth2")); // return converter; // } }
<font color='red'>注意:</font>
若是使用本地驗證方法,可能會報讀取不到oauth2.jks的錯誤,由於默認不引用resources目錄下的文件,須要在pom.xml中<build>下添加配置
<resources> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.*</include> </includes> </resource> </resources>
啓動順序:
經過zuul端口訪問eureka-client下的方法 http://localhost:9110/eureka-client/hi
會自動跳到oauth-server的登錄頁面,輸入用戶名和密碼登錄
看url,跳轉到了oauth/authorize,這是受權接口,而且後面攜帶了一些zuul配置的信息
成功
訪問eureka-client1不須要登錄
寫的比較簡潔,可是作出來真的花費了兩天的時間精力(仍是太菜了)
沒有什麼文采,原理性的東西也寫不出來,只能記錄一下實踐,你們共同交流
更多文章見我的博客 https://zheyday.github.io/