一,單點登陸概述html
(一)什麼是單點登陸:每一個子系統從第三方認證系統中查找而不是每一個系統都經過各自的session校驗。java
(三)單點登陸實現框架:mysql
apache Shiroweb
CASredis
springsecurity算法
二。Oauth2認證微信認證第三方登陸spring
1.受權碼模式:資源擁有者(用戶)發起微信登陸,平臺調用微信接口,到達受權頁面,手機wx掃碼登陸用戶贊成受權,微信會對用戶進行驗證,經過後給平臺一個受權碼,平臺sql
攜帶受權碼到微信認證服務申請令牌,並返回令牌到平臺,平臺再攜帶令牌調微信用戶信息服務,微信用戶信息服務校驗令牌合法性,響應給平臺,apache
平臺顯示微信頭像。json
客戶端(平臺)拿到受權碼去認證服務申請令牌,受權服務經過私鑰加密生成令牌,
令牌給客戶端,攜帶令牌訪問資源服務
課程服務至關於資源存儲公鑰(根據公鑰校驗令牌合法性===公鑰把令牌解開,放行;;解不開拒絕服務)
課程服務至關於資源服務
對swagger進行放行
"/swagger-resources","/swagger-resources/configuration/security", "/swagger-ui.html","/webjars/**","/course/coursepic/list/*").permitAll()
mport org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.stream.Collectors; @Configuration @EnableResourceServer @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//激活方法上的PreAuthorize註解 public class ResourceServerConfig extends ResourceServerConfigurerAdapter { //公鑰 private static final String PUBLIC_KEY = "publickey.txt"; //定義JwtTokenStore,使用jwt令牌 @Bean public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) { return new JwtTokenStore(jwtAccessTokenConverter); } //定義JJwtAccessTokenConverter,使用jwt令牌 @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setVerifierKey(getPubKey()); return converter; } /** * 獲取非對稱加密公鑰 Key * @return 公鑰 Key */ private String getPubKey() { Resource resource = new ClassPathResource(PUBLIC_KEY); try { InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream()); BufferedReader br = new BufferedReader(inputStreamReader); return br.lines().collect(Collectors.joining("\n")); } catch (IOException ioe) { return null; } } //Http安全配置,對每一個到達系統的http請求連接進行校驗 @Override public void configure(HttpSecurity http) throws Exception { //全部請求必須認證經過 http.authorizeRequests() .antMatchers("/v2/api-docs", "/swagger-resources/configuration/ui", "/swagger-resources","/swagger-resources/configuration/security", "/swagger-ui.html","/webjars/**","/course/coursepic/list/*").permitAll() .anyRequest().authenticated(); } }
訪問課程服務只有:頭部KEY:authorization
value:Bear+accesstoken
才能夠訪問
2.密碼算法模式
不用申請受權碼,用戶名,密碼就能夠;
jwt中包含了用戶信息,能夠避免資源服務解決不了驗證還要請求認證服務來驗證。效率高
是個json串便於解析,易拓展,非對稱安全,但長
分爲頭部(加密算法),負載(本身加),簽名(認證服務端簽發的惟一防止竊取)。
(一)認證服務的controller
如何申請令牌
clientid,clientpassword
bodyheader封裝在HTTPentity
getHttpBasic
MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); body.add("grant_type","password"); body.add("username","itcast"); body.add("password","123"); MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.add("Authorization",this.getHttpBasic("XcWebApp","XcWebApp")); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body,headers);
private String getHttpBasic(String clientId, String clientPassword) {
String value =clientId+":"+clientPassword ;
byte[] encode = Base64Utils.encode(value.getBytes());
return "Basic "+new String(encode);
}
uri
//http://localhost:40400/auth/oauth/token ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH); // http://localhost:40400 URI uri = serviceInstance.getUri(); String url = uri+"/auth/oauth/token";
ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
Map map = responseEntity.getBody();
1 Override 2 @PostMapping("/userlogin") 3 public LoginResult login(LoginRequest loginRequest) { 4 5 //判斷參數 6 if (StringUtils.isEmpty(loginRequest.getUsername())){ 7 ExceptionCast.cast(AuthCode.AUTH_USERNAME_NONE); 8 } 9 if (StringUtils.isEmpty(loginRequest.getPassword())){ 10 ExceptionCast.cast(AuthCode.AUTH_PASSWORD_NONE); 11 } 12 13 //申請令牌 14 AuthToken authToken = authService.login(loginRequest.getUsername(),loginRequest.getPassword(),clientId,clientSecret); 15 16 String jti = authToken.getJti(); 17 18 //將令牌信息存入cookie 19 this.saveTokenToCookie(jti); 20 21 return new LoginResult(CommonCode.SUCCESS,jti); 22 } 23 24 private void saveTokenToCookie(String jti) { 25 HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); 26 27 //httpOnly:false。 容許瀏覽器獲取cookie 28 CookieUtil.addCookie(response,cookieDomain,"/","uid",jti,cookieMaxAge,false); 29 }
測試
實際結果
(二)認證服務的service
public AuthToken login(String username, String password, String clientId, String clientSecret) { //申請令牌 AuthToken authToken = this.applyToken(username,password,clientId,clientSecret); //將令牌存入redis boolean result = this.saveTokenToRedis(authToken); if (!result){ //存入失敗 ExceptionCast.cast(AuthCode.AUTH_LOGIN_TOKEN_SAVEFAIL); } return authToken; } //存入redis private boolean saveTokenToRedis(AuthToken authToken) { String key = "user_token:"+authToken.getJti(); String tokenString = JSON.toJSONString(authToken); stringRedisTemplate.boundValueOps(key).set(tokenString,tokenValiditySeconds, TimeUnit.SECONDS); Long expire = stringRedisTemplate.getExpire(key); return expire>0; } //申請令牌 private AuthToken applyToken(String username, String password, String clientId, String clientSecret) { ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH); URI uri = serviceInstance.getUri(); String url = uri+"/auth/oauth/token"; MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); body.add("grant_type","password"); body.add("username",username); body.add("password",password); MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.add("Authorization",this.getHttpBasic(clientId,clientSecret)); HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers); restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ @Override public void handleError(ClientHttpResponse response) throws IOException { if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401){ super.handleError(response); } } }); ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class); Map map = responseEntity.getBody(); if (map == null || map.get("access_token")==null || map.get("refresh_token")==null || map.get("jti")==null){ ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL); } AuthToken authToken = new AuthToken(); authToken.setAccess_token((String) map.get("access_token")); authToken.setRefresh_token((String) map.get("refresh_token")); authToken.setJti((String) map.get("jti")); return authToken; }
三,具體單點登陸實現認證服務
(一)配置文件
1
AuthorizationServerConfig
密鑰非對稱加密,私鑰加密,公鑰解密
package com.xuecheng.auth.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.bootstrap.encrypt.KeyProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; 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.ClientDetailsService; import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; import javax.annotation.Resource; import javax.sql.DataSource; import java.security.KeyPair; @Configuration @EnableAuthorizationServer class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; //jwt令牌轉換器 @Autowired private JwtAccessTokenConverter jwtAccessTokenConverter; @Autowired UserDetailsService userDetailsService; @Autowired AuthenticationManager authenticationManager; @Autowired TokenStore tokenStore; @Autowired private CustomUserAuthenticationConverter customUserAuthenticationConverter; //讀取密鑰的配置 @Bean("keyProp") public KeyProperties keyProperties(){ return new KeyProperties(); } @Resource(name = "keyProp") private KeyProperties keyProperties; //客戶端配置 @Bean public ClientDetailsService clientDetails() { return new JdbcClientDetailsService(dataSource); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(this.dataSource).clients(this.clientDetails()); /* clients.inMemory() .withClient("XcWebApp")//客戶端id .secret("XcWebApp")//密碼,要保密 .accessTokenValiditySeconds(60)//訪問令牌有效期 .refreshTokenValiditySeconds(60)//刷新令牌有效期 //受權客戶端請求認證服務的類型authorization_code:根據受權碼生成令牌, // client_credentials:客戶端認證,refresh_token:刷新令牌,password:密碼方式認證 .authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token", "password") .scopes("app");//客戶端範圍,名稱自定義,必填*/ } //token的存儲方法 // @Bean // public InMemoryTokenStore tokenStore() { // //將令牌存儲到內存 // return new InMemoryTokenStore(); // } // @Bean // public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory){ // RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory); // return redisTokenStore; // } @Bean @Autowired public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) { return new JwtTokenStore(jwtAccessTokenConverter); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter(CustomUserAuthenticationConverter customUserAuthenticationConverter) { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); KeyPair keyPair = new KeyStoreKeyFactory (keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getSecret().toCharArray()) .getKeyPair(keyProperties.getKeyStore().getAlias(),keyProperties.getKeyStore().getPassword().toCharArray()); converter.setKeyPair(keyPair); //配置自定義的CustomUserAuthenticationConverter DefaultAccessTokenConverter accessTokenConverter = (DefaultAccessTokenConverter) converter.getAccessTokenConverter(); accessTokenConverter.setUserTokenConverter(customUserAuthenticationConverter); return converter; } //受權服務器端點配置 @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { /*Collection<TokenEnhancer> tokenEnhancers = applicationContext.getBeansOfType(TokenEnhancer.class).values(); TokenEnhancerChain tokenEnhancerChain=new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers(new ArrayList<>(tokenEnhancers)); DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); defaultTokenServices.setReuseRefreshToken(true); defaultTokenServices.setSupportRefreshToken(true); defaultTokenServices.setTokenStore(tokenStore); defaultTokenServices.setAccessTokenValiditySeconds(1111111); defaultTokenServices.setRefreshTokenValiditySeconds(1111111); defaultTokenServices.setTokenEnhancer(tokenEnhancerChain); endpoints .authenticationManager(authenticationManager) .userDetailsService(userDetailsService) //.tokenStore(tokenStore); .tokenServices(defaultTokenServices);*/ endpoints.accessTokenConverter(jwtAccessTokenConverter) .authenticationManager(authenticationManager)//認證管理器 .tokenStore(tokenStore)//令牌存儲 .userDetailsService(userDetailsService);//用戶信息service } //受權服務器的安全配置 @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { // oauthServer.checkTokenAccess("isAuthenticated()");//校驗token須要認證經過,可採用http basic認證 oauthServer.allowFormAuthenticationForClients() .passwordEncoder(new BCryptPasswordEncoder()) .tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); } }
2
CustomUserAuthenticationConverter
生成令牌信息
package com.xuecheng.auth.config; import com.xuecheng.auth.service.UserJwt; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.AuthorityUtils; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter; import org.springframework.stereotype.Component; import java.util.LinkedHashMap; import java.util.Map; @Component public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter { @Autowired UserDetailsService userDetailsService; @Override public Map<String, ?> convertUserAuthentication(Authentication authentication) { LinkedHashMap response = new LinkedHashMap(); String name = authentication.getName(); response.put("user_name", name); Object principal = authentication.getPrincipal(); UserJwt userJwt = null; if(principal instanceof UserJwt){ userJwt = (UserJwt) principal; }else{ //refresh_token默認不去調用userdetailService獲取用戶信息,這裏咱們手動去調用,獲得 UserJwt UserDetails userDetails = userDetailsService.loadUserByUsername(name); userJwt = (UserJwt) userDetails; } response.put("name", userJwt.getName()); response.put("id", userJwt.getId()); response.put("utype",userJwt.getUtype()); response.put("userpic",userJwt.getUserpic()); response.put("companyId",userJwt.getCompanyId()); if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) { response.put("authorities", AuthorityUtils.authorityListToSet(authentication.getAuthorities())); } return response; } }
3
WebSecurityConfig
對登陸放行
密碼加鹽加密
1 import org.springframework.context.annotation.Bean; 2 import org.springframework.context.annotation.Configuration; 3 import org.springframework.core.annotation.Order; 4 import org.springframework.security.authentication.AuthenticationManager; 5 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 6 import org.springframework.security.config.annotation.web.builders.WebSecurity; 7 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 8 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 9 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 10 import org.springframework.security.crypto.password.PasswordEncoder; 11 12 @Configuration 13 @EnableWebSecurity 14 @Order(-1) 15 class WebSecurityConfig extends WebSecurityConfigurerAdapter { 16 17 @Override 18 public void configure(WebSecurity web) throws Exception { 19 web.ignoring().antMatchers("/userlogin","/userlogout","/userjwt"); 20 21 } 22 @Bean 23 @Override 24 public AuthenticationManager authenticationManagerBean() throws Exception { 25 AuthenticationManager manager = super.authenticationManagerBean(); 26 return manager; 27 } 28 //採用bcrypt對密碼進行編碼 29 @Bean 30 public PasswordEncoder passwordEncoder() { 31 return new BCryptPasswordEncoder(); 32 } 33 34 @Override 35 public void configure(HttpSecurity http) throws Exception { 36 http.csrf().disable() 37 .httpBasic().and() 38 .formLogin() 39 .and() 40 .authorizeRequests().anyRequest().authenticated(); 41 42 } 43 }
authservice寫認證
package com.xuecheng.auth.service; import com.alibaba.fastjson.JSON; import com.xuecheng.filesystem.framework.client.XcServiceList; import com.xuecheng.filesystem.framework.domain.ucenter.ext.AuthToken; import com.xuecheng.filesystem.framework.domain.ucenter.response.AuthCode; import com.xuecheng.filesystem.framework.exception.ExceptionCast; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.http.client.ClientHttpResponse; import org.springframework.stereotype.Service; import org.springframework.util.Base64Utils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.RestTemplate; import java.io.IOException; import java.net.URI; import java.util.Map; import java.util.concurrent.TimeUnit; @Service public class AuthService { @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancerClient loadBalancerClient; @Autowired private StringRedisTemplate stringRedisTemplate; @Value("${auth.tokenValiditySeconds}") private long tokenValiditySeconds; /** * 用戶認證登陸,申請令牌 * @param username * @param password * @param clientId * @param clientSecret * @return */ public AuthToken login(String username, String password, String clientId, String clientSecret) { //申請令牌 AuthToken authToken = this.applyToken(username,password,clientId,clientSecret); //將令牌存入redis boolean result = this.saveTokenToRedis(authToken); if (!result){ //存入失敗 ExceptionCast.cast(AuthCode.AUTH_LOGIN_TOKEN_SAVEFAIL); } return authToken; } //存入redis private boolean saveTokenToRedis(AuthToken authToken) { String key = "user_token:"+authToken.getJti(); String tokenString = JSON.toJSONString(authToken); stringRedisTemplate.boundValueOps(key).set(tokenString,tokenValiditySeconds, TimeUnit.SECONDS); Long expire = stringRedisTemplate.getExpire(key); return expire>0; } //申請令牌 private AuthToken applyToken(String username, String password, String clientId, String clientSecret) { ServiceInstance serviceInstance = loadBalancerClient.choose(XcServiceList.XC_SERVICE_UCENTER_AUTH); URI uri = serviceInstance.getUri(); String url = uri+"/auth/oauth/token"; MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); body.add("grant_type","password"); body.add("username",username); body.add("password",password); MultiValueMap<String, String> headers = new LinkedMultiValueMap<>(); headers.add("Authorization",this.getHttpBasic(clientId,clientSecret)); HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(body,headers); restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){ @Override public void handleError(ClientHttpResponse response) throws IOException { if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401){ super.handleError(response); } } }); ResponseEntity<Map> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class); Map map = responseEntity.getBody(); if (map == null || map.get("access_token")==null || map.get("refresh_token")==null || map.get("jti")==null){ ExceptionCast.cast(AuthCode.AUTH_LOGIN_APPLYTOKEN_FAIL); } AuthToken authToken = new AuthToken(); authToken.setAccess_token((String) map.get("access_token")); authToken.setRefresh_token((String) map.get("refresh_token")); authToken.setJti((String) map.get("jti")); return authToken; } private String getHttpBasic(String clientId, String clientSecret) { String value = clientId+":"+clientSecret; byte[] encode = Base64Utils.encode(value.getBytes()); return "Basic "+new String(encode); } public AuthToken getTokenFormRedis(String jti) { String key="user_token:"+jti; String tokenString = stringRedisTemplate.boundValueOps(key).get(); AuthToken authToken = JSON.parseObject(tokenString, AuthToken.class); return authToken; } public void delTokenFromRedis(String jti) { String key="user_token:"+jti; stringRedisTemplate.delete(key); } }
userjwt用戶信息融到令牌中
import lombok.Data; import lombok.ToString; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import java.util.Collection; @Data @ToString public class UserJwt extends User { private String id; private String name; private String userpic; private String utype; private String companyId; public UserJwt(String username, String password, Collection<? extends GrantedAuthority> authorities) { super(username, password, authorities); } }
yml配置
1訪問路徑,redis信息
2auth設置redis過時時間==session過時時間(過時從新登陸用)
3私鑰位置
4cookie域名(適配到不一樣域中)和maxage
server: port: ${PORT:40400} servlet: context-path: /auth spring: application: name: xc-service-ucenter-auth redis: host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} timeout: 5000 #鏈接超時 毫秒 jedis: pool: maxActive: 3 maxIdle: 3 minIdle: 1 maxWait: -1 #鏈接池最大等行時間 -1沒有限制 datasource: druid: url: ${MYSQL_URL:jdbc:mysql://localhost:3306/xc_user?characterEncoding=utf-8} username: root password: root driverClassName: com.mysql.jdbc.Driver initialSize: 5 #初始創建鏈接數量 minIdle: 5 #最小鏈接數量 maxActive: 20 #最大鏈接數量 maxWait: 10000 #獲取鏈接最大等待時間,毫秒 testOnBorrow: true #申請鏈接時檢測鏈接是否有效 testOnReturn: false #歸還鏈接時檢測鏈接是否有效 timeBetweenEvictionRunsMillis: 60000 #配置間隔檢測鏈接是否有效的時間(單位是毫秒) minEvictableIdleTimeMillis: 300000 #鏈接在鏈接池的最小生存時間(毫秒) auth: tokenValiditySeconds: 1200 #token存儲到redis的過時時間 clientId: XcWebApp clientSecret: XcWebApp cookieDomain: xuecheng.com cookieMaxAge: -1 encrypt: key-store: location: classpath:/xc.keystore secret: xuechengkeystore alias: xckey password: xuecheng eureka: client: registerWithEureka: true #服務註冊開關 fetchRegistry: true #服務發現開關 serviceUrl: #Eureka客戶端與Eureka服務端進行交互的地址,多箇中間用逗號分隔 defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/,http://localhost:50102/eureka/} instance: prefer-ip-address: true #將本身的ip地址註冊到Eureka服務中 ip-address: ${IP_ADDRESS:127.0.0.1} instance-id: ${spring.application.name}:${server.port} #指定實例id ribbon: MaxAutoRetries: 2 #最大重試次數,當Eureka中能夠找到服務,可是服務連不上時將會重試,若是eureka中找不到服務則直接走斷路器 MaxAutoRetriesNextServer: 3 #切換實例的重試次數 OkToRetryOnAllOperations: false #對全部操做請求都進行重試,若是是get則能夠,若是是post,put等操做沒有實現冪等的狀況下是很危險的,因此設置爲false ConnectTimeout: 5000 #請求鏈接的超時時間 ReadTimeout: 6000 #請求處理的超時時間