Spring Cloud Alibaba 實戰

點擊上方藍色「程序猿Damon」,選擇「設爲星標」javascript

回覆「yeah」獲取整理的學習資料css



2018年11月左右,Springcloud 聯合創始人Spencer Gibb在Spring官網的博客頁面宣佈:阿里巴巴開源 Spring Cloud Alibaba,併發布了首個預覽版本。隨後,Spring Cloud 官方Twitter也發佈了此消息。java


目前版本以下:mysql


Spring Cloud Spring Cloud Alibaba Spring Boot 

Spring Cloud Hoxtonreact

2.2.0.RELEASEgit

2.2.X.RELEASEgithub

Spring Cloud Greenwichweb

2.1.1.RELEASE面試

2.1.X.RELEASEredis

Spring Cloud Finchley

2.0.1.RELEASE

2.0.X.RELEASE

Spring Cloud Edgware

1.5.1.RELEASE

1.5.X.RELEASE


Spring Cloud Hoxton SR3 前不久發佈,基於 Spring Boot 2.2.5 構建。也就是說最新的版本是 Hoxton 版本。但怕最新版有沙坑,咱們本次用的是Greenwich 版本。並且,阿里巴巴的官方版本有的對於一些依賴有問題,咱們用的是孵化器版本,其依賴關係:


Spring  Cloud  Spring Cloud Alibaba  Spring Boot

Spring Cloud Greenwich

0.9.0.RELEASE

2.1.X.RELEASE

Spring Cloud Finchley

0.2.X.RELEASE

2.0.X.RELEASE

Spring Cloud Edgware

0.1.X.RELEASE

1.5.X.RELEASE


1、環境準備


  • Spring Boot: 2.1.8


  • Spring Cloud: Greenwich.SR3


  • Spring Cloud Alibaba: 0.9.0.RELEASE


  • Maven: 3.5.4


  • Java 1.8 +


  • Oauth2 (Spring Security 5.1.6 +)


2、實戰

項目模塊

主要分爲: 鑑權中心、服務提供者、服務消費者、網關

實戰代碼

鑑權中心,依賴pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.damon</groupId> <artifactId>oauth-cas</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>oauth-cas</name> <url>http://maven.apache.org</url>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <swagger.version>2.6.1</swagger.version> <xstream.version>1.4.7</xstream.version> <pageHelper.version>4.1.6</pageHelper.version> <fastjson.version>1.2.51</fastjson.version> <!-- <springcloud.version>2.1.8.RELEASE</springcloud.version> --> <springcloud.version>Greenwich.SR3</springcloud.version> <springcloud.kubernetes.version>1.1.1.RELEASE</springcloud.kubernetes.version> <mysql.version>5.1.46</mysql.version> <alibaba-cloud.version>2.1.1.RELEASE</alibaba-cloud.version> <springcloud.alibaba.version>0.9.0.RELEASE</springcloud.alibaba.version> </properties>
<dependencyManagement> <dependencies> <!-- <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${alibaba-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> -->
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${springcloud.alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${springcloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>4.6.3</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> <!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <!--分頁插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pageHelper.version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- datasource pool--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.3</version> </dependency> <!-- 對redis支持,引入的話項目緩存就支持redis了,因此必須加上redis的相關配置,不然操做相關緩存會報異常 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>org.jsoup</groupId> <artifactId>jsoup</artifactId> <version>1.11.3</version> </dependency> </dependencies>
<build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> <fork>true</fork> </configuration> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.8</version> <executions> <execution> <goals> <goal>prepare-agent</goal> <goal>report</goal> </goals> </execution> </executions>      </plugin> </plugins> </build></project>


本例中,用到了 Nacos 做爲註冊中心、配置中心,估須要引入其依賴:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>  <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>


Oauth2 的依賴:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency>


同時利用 redis 來處理鑑權的信息存儲:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>


接下來須要準備配置文件 yaml:

management: endpoint: restart: enabled: true health: enabled: true info: enabled: true
spring: application: name: oauth-cas cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:8848 refreshable-dataids: actuator.properties,log.properties redis: #redis相關配置 database: 8    host: 127.0.0.1 port: 6379    password: qwqwsq jedis: pool: max-active: 8 max-idle: 8 min-idle: 0 timeout: 10000ms http: encoding: charset: UTF-8 enabled: true force: true mvc: throw-exception-if-no-handler-found: true main: allow-bean-definition-overriding: true # 當遇到一樣名稱時,是否容許覆蓋註冊 logging: path: /data/${spring.application.name}/logs


注意,這個配置文件須要是 bootstrap,不然可能失敗,至於爲何,你們能夠本身試試。


接下來就是 application:

server: port: 2000 undertow: accesslog: enabled: false pattern: combined servlet: session: timeout: PT120M  client: http: request: connectTimeout: 8000 readTimeout: 30000 mybatis: mapperLocations: classpath:mapper/*.xml  typeAliasesPackage: com.damon.*.model


配置完成後,完成 main:

package com.damon;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;

/** * * 配置最多的就是認證服務端,驗證帳號、密碼,存儲 token,檢查 token ,刷新 token 等都是認證服務端的工做 * @author Damon * @date 2020年1月13日 下午2:29:42 * */@Configuration@EnableAutoConfiguration@ComponentScan(basePackages = {"com.damon"})@EnableDiscoveryClientpublic class CasApp { public static void main(String[] args) { SpringApplication.run(CasApp.class, args); }}


接下來就是配置幾個 Oauth2 服務端的幾個配置類:AuthorizationServerConfig、ResourceServerConfig、SecurityConfig、RedisTokenStoreConfig、MyRedisTokenStore、UserOAuth2WebResponseExceptionTranslator、AuthenticationEntryPointHandle 等。在 Springcloud Oauth2 進階篇Springcloud Oauth2 HA篇 等幾篇中已經講過了。對於相關代碼能夠關注個人公衆號和我互動。


其中最重要的就是登陸時的函數:

package com.damon.login.service.impl;
import java.util.List;
import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.password.PasswordEncoder;import org.springframework.security.oauth2.common.OAuth2AccessToken;import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;import org.springframework.stereotype.Service;
import com.damon.commons.Response;import com.damon.constant.Constant;import com.damon.constant.LoginEnum;import com.damon.exception.InnerErrorException;import com.damon.login.dao.UserMapper;import com.damon.login.model.SysUser;import com.damon.login.service.LoginService;import com.damon.utils.IpUtil;import com.google.common.collect.Lists;
/** * @author wangshoufa * @date 2018年11月15日 下午12:01:53 * */@Servicepublic class LoginServiceImpl implements LoginService {
Logger logger = LoggerFactory.getLogger(LoginServiceImpl.class);
//private List<User> userList; @Autowired private PasswordEncoder passwordEncoder; @Autowired private UserMapper userMapper; @Autowired    private HttpServletRequest req; /** * Auth * 登陸認證 * 實際中從數據庫獲取信息 * 這裏爲了作演示,把用戶名、密碼和所屬角色都寫在代碼裏了,正式環境中,這裏應該是從數據庫或者其餘地方根據用戶名將加密後的密碼及所屬角色查出來的。帳號 damon , * 密碼123456,稍後在換取 token 的時候會用到。而且給這個用戶設置 "ROLE_ADMIN" 角色。 * */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.info("clientIp is: {} ,username: {}", IpUtil.getClientIp(req), username); logger.info("serverIp is: {}", IpUtil.getCurrentIp()); // 查詢數據庫操做 try { SysUser user = userMapper.getUserByUsername(username); if (user == null) { logger.error("user not exist"); throw new UsernameNotFoundException("username is not exist"); //throw new UsernameNotFoundException("the user is not found"); } else { // 用戶角色也應在數據庫中獲取,這裏簡化 String role = ""; if(user.getIsAdmin() == 1) { role = "admin"; } List<SimpleGrantedAuthority> authorities = Lists.newArrayList(); authorities.add(new SimpleGrantedAuthority(role)); //String password = passwordEncoder.encode("123456");// 123456是密碼 //return new User(username, password, authorities); // 線上環境應該經過用戶名查詢數據庫獲取加密後的密碼 return new User(username, user.getPassword(), authorities); } } catch (Exception e) { logger.error("database collect failed"); logger.error(e.getMessage(), e); throw new UsernameNotFoundException(e.getMessage()); }  }  }
函數   loadUserByUsername 須要驗證數據庫的密碼,而且給用戶受權角色。

到此,鑑權中心服務端完成。上面說的利用了 Nacos 來做爲註冊中心被客戶端服務發現,並提供配置管理。

下載 Nacos 地址:https://github.com/alibaba/nacos/releases
版本:v1.2.1

執行:

  • Linux/Unix/Mac:sh startup.sh -m standalone

  • Windows:cmd startup.cmd -m standalone


啓動完成以後,訪問:http://127.0.0.1:8848/nacos/,能夠進入Nacos的服務管理頁面,具體以下:


默認用戶名與密碼都是nacos。


登錄後打開服務管理,能夠看到註冊到 Nacos 的服務列表:


能夠點擊配置管理,查看配置:



若是沒有配置任何服務的配置,能夠新建:




上面講述了Nacos 如何做爲註冊中心與配置中心的,很簡單吧。

接下來咱們講解服務提供者代碼:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.damon</groupId> <artifactId>provider-service</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>provider-service</name> <url>http://maven.apache.org</url>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <swagger.version>2.6.1</swagger.version> <xstream.version>1.4.7</xstream.version> <pageHelper.version>4.1.6</pageHelper.version> <fastjson.version>1.2.51</fastjson.version> <!-- <springcloud.version>2.1.8.RELEASE</springcloud.version> --> <springcloud.version>Greenwich.SR3</springcloud.version> <springcloud.kubernetes.version>1.1.1.RELEASE</springcloud.kubernetes.version> <mysql.version>5.1.46</mysql.version> <alibaba-cloud.version>2.1.1.RELEASE</alibaba-cloud.version> <springcloud.alibaba.version>0.9.0.RELEASE</springcloud.alibaba.version> </properties>
<dependencyManagement> <dependencies> <!-- <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${alibaba-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> -->
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${springcloud.alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${springcloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-undertow</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- swagger --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>${swagger.version}</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.2</version> </dependency> <!--分頁插件--> <dependency> <groupId>com.github.pagehelper</groupId> <artifactId>pagehelper</artifactId> <version>${pageHelper.version}</version> </dependency> <!-- mybatis --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- datasource pool--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.3</version> </dependency> <!-- 對redis支持,引入的話項目緩存就支持redis了,因此必須加上redis的相關配置,不然操做相關緩存會報異常 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version> </dependency> </dependencies>
<build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> <fork>true</fork> </configuration> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.8</version> <executions> <execution> <goals> <goal>prepare-agent</goal> <goal>report</goal> </goals> </execution> </executions> </plugin> <!-- 自動生成代碼 插件 begin --> <!-- <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <dependencies> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> </dependencies> </plugin> --> </plugins> </build></project>

一如既往的引入依賴。


配置 bootstrap 文件;
management: endpoint: restart: enabled: true health: enabled: true info: enabled: true spring: application:    name: provider-service  cloud: nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:8848 refreshable-dataids: actuator.properties,log.properties  http: encoding: charset: UTF-8 enabled: true force: true mvc: throw-exception-if-no-handler-found: true main: allow-bean-definition-overriding: true #當遇到一樣名稱時,是否容許覆蓋註冊 
logging: path: /data/${spring.application.name}/logs
cas-server-url: http://oauth-cas #http://localhost:2000#設置能夠訪問的地址
security: oauth2: #與cas對應的配置 client: client-id: provider-service client-secret: provider-service-123 user-authorization-uri: ${cas-server-url}/oauth/authorize #是受權碼認證方式須要的 access-token-uri: ${cas-server-url}/oauth/token #是密碼模式須要用到的獲取 token 的接口 resource: loadBalanced: true #jwt: #jwt存儲token時開啓 #key-uri: ${cas-server-url}/oauth/token_key #key-value: test_jwt_sign_key id: provider-service #指定用戶信息地址 user-info-uri: ${cas-server-url}/api/user #指定user info的URI,原生地址後綴爲/auth/user prefer-token-info: false #token-info-uri: authorization: check-token-access: ${cas-server-url}/oauth/check_token #當此web服務端接收到來自UI客戶端的請求後,須要拿着請求中的 token 到認證服務端作 token 驗證,就是請求的這個接口

application 文件;
server: port: 2001 undertow: accesslog: enabled: false pattern: combined servlet: session: timeout: PT120M cookie: name: PROVIDER-SERVICE-SESSIONID #防止Cookie衝突,衝突會致使登陸驗證不經過 
client: http: request: connectTimeout: 8000 readTimeout: 30000 mybatis: mapperLocations: classpath:mapper/*.xml typeAliasesPackage: com.damon.*.model
backend: ribbon: client: enabled: true ServerListRefreshInterval: 5000
ribbon: ConnectTimeout: 3000 # 設置全局默認的ribbon的讀超時 ReadTimeout: 1000 eager-load: enabled: true clients: oauth-cas,consumer-service MaxAutoRetries: 1 #對第一次請求的服務的重試次數 MaxAutoRetriesNextServer: 1 #要重試的下一個服務的最大數量(不包括第一個服務) #listOfServers: localhost:5556,localhost:5557 #ServerListRefreshInterval: 2000 OkToRetryOnAllOperations: true NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
hystrix.command.BackendCall.execution.isolation.thread.timeoutInMilliseconds: 5000hystrix.threadpool.BackendCallThread.coreSize: 5

接下來啓動類:
package com.damon;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;

/** * @author Damon * @date 2020年1月13日 下午3:23:06 * */
@Configuration@EnableAutoConfiguration@ComponentScan(basePackages = {"com.damon"})@EnableDiscoveryClient@EnableOAuth2Ssopublic class ProviderApp {
public static void main(String[] args) { SpringApplication.run(ProviderApp.class, args); }
}

注意:註解 @EnableDiscoveryClient、@EnableOAuth2Sso 都須要。


這時,一樣須要配置 ResourceServerConfig、SecurityConfig。

若是須要數據庫,能夠加上:
package com.damon.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.mybatis.spring.annotation.MapperScan;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.env.Environment;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.druid.pool.DruidDataSourceFactory;import com.github.pagehelper.PageHelper;
/***** created by wangshoufa* 2018年5月23日 下午7:39:37**/@Component@Configuration@EnableTransactionManagement@MapperScan("com.damon.*.dao")public class MybaitsConfig {
@Autowired private EnvConfig envConfig; @Autowired private Environment env;
@Bean(name = "dataSource") public DataSource getDataSource() throws Exception { Properties props = new Properties(); props.put("driverClassName", envConfig.getJdbc_driverClassName()); props.put("url", envConfig.getJdbc_url()); props.put("username", envConfig.getJdbc_username()); props.put("password", envConfig.getJdbc_password()); return DruidDataSourceFactory.createDataSource(props); }
@Bean public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean fb = new SqlSessionFactoryBean(); // 指定數據源(這個必須有,不然報錯) fb.setDataSource(dataSource); // 下邊兩句僅僅用於*.xml文件,若是整個持久層操做不須要使用到xml文件的話(只用註解就能夠搞定),則不加 fb.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage"));// 指定基包 fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations")));// 指定xml文件位置
// 分頁插件 PageHelper pageHelper = new PageHelper(); Properties props = new Properties(); // 啓用合理化時,若是pageNum<1會查詢第一頁,若是pageNum>pages會查詢最後一頁 //禁用合理化時,若是pageNum<1或pageNum>pages會返回空數據 props.setProperty("reasonable", "true"); //指定數據庫 props.setProperty("dialect", "mysql"); //支持經過Mapper接口參數來傳遞分頁參數 props.setProperty("supportMethodsArguments", "true"); //老是返回PageInfo類型,check檢查返回類型是否爲PageInfo,none返回Page props.setProperty("returnPageInfo", "check"); props.setProperty("params", "count=countSql"); pageHelper.setProperties(props); // 添加插件 fb.setPlugins(new Interceptor[] { pageHelper });
try { return fb.getObject(); } catch (Exception e) { throw e; } }
/** * 配置事務管理器 * @param dataSource * @return * @throws Exception */ @Bean public DataSourceTransactionManager transactionManager(DataSource dataSource) throws Exception { return new DataSourceTransactionManager(dataSource); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) { return new SqlSessionTemplate(sqlSessionFactory); }
}


接下來新寫一個 controller 類:
package com.damon.user.controller;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.security.core.Authentication;import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import com.damon.commons.Response;import com.damon.user.service.UserService;
/** * * * @author Damon * @date 2020年1月13日 下午3:31:07 * */@RestController@RequestMapping("/api/user")public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @GetMapping("/getCurrentUser") @PreAuthorize("hasAuthority('admin')") public Object getCurrentUser(Authentication authentication) { logger.info("test password mode"); return authentication; }
@PreAuthorize("hasAuthority('admin')") @GetMapping("/auth/admin") public Object adminAuth() { logger.info("test password mode"); return "Has admin auth!"; } @GetMapping(value = "/get") @PreAuthorize("hasAuthority('admin')") //@PreAuthorize("hasRole('admin')")//無效 public Object get(Authentication authentication){ //Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); authentication.getCredentials(); OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)authentication.getDetails(); String token = details.getTokenValue(); return token; } @GetMapping("/getUserInfo") @PreAuthorize("hasAuthority('admin')") public Response<Object> getUserInfo(Authentication authentication) { logger.info("test password mode"); Object principal = authentication.getPrincipal(); if(principal instanceof String) { String username = (String) principal; return userService.getUserByUsername(username); } return null; }
}

基本上一個代碼就完成了。接下來測試一下:
認證:curl -i -X POST -d "username=admin&password=123456&grant_type=password&client_id=provider-service&client_secret=provider-service-123" http://localhost:5555/oauth-cas/oauth/token
拿到token後:curl -i -H "Accept: application/json" -H "Authorization:bearer f4a42baa-a24a-4342-a00b-32cb135afce9" -X GET http://localhost:5555/provider-service/api/user/getCurrentUser

這裏用到了 5555 端口,這是一個網關服務,好吧,既然提到這個,咱們接下來看網關吧,引入依賴:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion>
<groupId>com.damon</groupId> <artifactId>alibaba-gateway</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging>
<name>alibaba-gateway</name> <url>http://maven.apache.org</url>
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.8.RELEASE</version> <relativePath/> </parent>
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <swagger.version>2.6.1</swagger.version> <xstream.version>1.4.7</xstream.version> <pageHelper.version>4.1.6</pageHelper.version> <fastjson.version>1.2.51</fastjson.version> <!-- <springcloud.version>2.1.8.RELEASE</springcloud.version> --> <springcloud.version>Greenwich.SR3</springcloud.version> <springcloud.kubernetes.version>1.1.1.RELEASE</springcloud.kubernetes.version> <mysql.version>5.1.46</mysql.version> <alibaba-cloud.version>2.1.1.RELEASE</alibaba-cloud.version> <springcloud.alibaba.version>0.9.0.RELEASE</springcloud.alibaba.version> </properties>
<dependencyManagement> <dependencies> <!-- <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${alibaba-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> -->
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${springcloud.alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${springcloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
<dependencies> <!-- 不要依賴spring-boot-starter-web,會和spring-cloud-starter-gateway衝突,啓動時異常 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--基於 reactive stream 的redis --> <!-- <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-commons</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>19.0</version> </dependency> </dependencies> <build> <finalName>${project.artifactId}</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <jvmArguments>-Dfile.encoding=UTF-8</jvmArguments> <fork>true</fork> </configuration> </plugin> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>0.7.8</version> <executions> <execution> <goals> <goal>prepare-agent</goal> <goal>report</goal> </goals> </execution> </executions> </plugin> <!-- 自動生成代碼 插件 begin --> <!-- <plugin> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-maven-plugin</artifactId> <version>1.3.2</version> <configuration> <configurationFile>src/main/resources/generatorConfig.xml</configurationFile> <verbose>true</verbose> <overwrite>true</overwrite> </configuration> <dependencies> <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>mybatis-generator-core</artifactId> <version>1.3.2</version> </dependency> </dependencies> </plugin> --> </plugins> </build></project>

一樣利用 Nacos 來發現服務。


相關配置在  Spring Cloud Kubernetes之實戰三網關Gateway 一文中有講過,這裏的註冊配置改成:
spring: cloud: gateway: discovery: locator: enabled: true #而且咱們並無給每個服務單獨配置路由 而是使用了服務發現自動註冊路由的方式 lowerCaseServiceId: true  nacos: discovery: server-addr: 127.0.0.1:8848 config: server-addr: 127.0.0.1:8848 refreshable-dataids: actuator.properties,log.properties
前面用的是 kubernetes。

好了,網關配置好後,啓動在 Nacos dashboard能夠看到該服務,表示註冊服務成功。接下來就能夠利用其來調用其餘服務了。具體 curl 命令:
curl -i -H "Accept: application/json" -H "Authorization:bearer f4a42baa-a24a-4342-a00b-32cb135afce9" -X GET http://localhost:5555/consumer-service/api/order/getUserInfo

Ok,到此鑑權中心、服務提供者、服務消費者、 服務的註冊與發現、配置中心等功能已完成。若是須要完整源碼,能夠關注公衆號,聯繫我,謝謝。

熱文推薦

微服務自動化部署CI/CD

淺談開發與研發之差別

面試被問 Spring cloud 上下文,能夠這樣回答

基於 Sentinel 做熔斷 | 文末贈資料

基礎設施服務k8s快速部署之HA篇

今天被問微服務,這幾點,讓面試官另眼相看

Spring cloud 之多種方式限流(實戰)

Spring cloud 之熔斷機制(實戰)

面試被問finally 和 return,到底誰先執行?

Springcloud Oauth2 HA篇

Spring Cloud Kubernetes之實戰一配置管理

Spring Cloud Kubernetes之實戰二服務註冊與發現

Spring Cloud Kubernetes之實戰三網關Gateway





求關注

關注公衆號,回覆入羣,獲取更多驚喜!公衆號(程序猿Damon)裏回覆 ES、Flink、Java、Kafka、MQ、ML、監控、大數據、k8s 等關鍵字能夠查看更多關鍵字對應的文章。




若有收穫,點個在看,謝謝

本文分享自微信公衆號 - 程序猿Damon(Damon4X)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索