天天看點

14. 微服務綜合案例2 zipkin dashboard turbine uaa (2刷)1. zipkin-service工程2. monitoring-server工程3. uaa-service

1. zipkin-service工程

pom

  • 最新版本的 zipkin-server不是這樣使用
  • zipkin server要去官網下jar包
  • 它現在不支援sdk的形式嵌入了
<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/>
    </parent>

	<spring-cloud.version>Greenwich.SR2</spring-cloud.version>

        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-server</artifactId>
            <version>2.11.8</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-slf4j-impl</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
            <version>2.11.8</version>
        </dependency>


		<!--
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-storage-mysql</artifactId>
            <version>2.4.1</version>
        </dependency> -->

		starter-web
		eureka-client

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

    </dependencies>
           

yaml 和 enable

spring:
  application:
    name: zipkin-server
server:
  port: 9411

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#關閉自動收集web請求
management:
  metrics:
    web:
      server:
        auto-time-requests: false
           
@EnableEurekaClient
@EnableZipkinServer //已經過時
           

2. monitoring-server工程

pom

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

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

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

		<!--hystrix-dashboard-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
		</dependency>

		<!--hystrix -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
		</dependency>

           

yaml 和 main方法

spring:
  application:
    name: monitor-service
  cloud:
    config:
      uri: http://localhost:8769
      fail-fast: true
  profiles:
      active: pro
           
@SpringBootApplication //boot
@EnableEurekaClient //eurekaClient
@EnableDiscoveryClient //服務發現client,上面不用開啟了
@RestController //json controller
@EnableHystrix //hystrix
@EnableHystrixDashboard //hystrix dashboard
@EnableCircuitBreaker //circuit breaker 要在SpringCloud中使用斷路器,需要加上
@EnableTurbine //turbine
public class MonitorServiceApplication {

	public static void main(String[] args) {
		SpringApplication.run(MonitorServiceApplication.class, args);
	}
}
           

沒有這個配置

feign:
  hystrix:
    enabled: true
           

3. uaa-service

流程

  1. 浏覽器 使用者名 + 密碼,到 user_blog, 加入 clientId,請求到 uaa 授權伺服器
  2. uaa驗證 clientId username 和 pwd,傳回JWT
  3. 浏覽器 得到 userInfo 和 JWT
  4. 浏覽器 header加入 JWT
  5. user_blog 解密JWT,驗證權限。 有權限 ,傳回資源

pom

<dependencies>
		<!-- 配置-->
		starter-config
		starter-web
        
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-jwt</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.security.oauth</groupId>
			<artifactId>spring-security-oauth2</artifactId>
		</dependency>

		starter-netflix-eureka-client

		<dependency> jpa
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
        
		starter-actuator
        
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-resources-plugin</artifactId>
				<configuration>
					<nonFilteredFileExtensions> jks
						<nonFilteredFileExtension>cert</nonFilteredFileExtension>
						<nonFilteredFileExtension>jks</nonFilteredFileExtension>
					</nonFilteredFileExtensions>
				</configuration>
			</plugin>
		</plugins>
	</build>
           

yaml

spring:
  application:
    name: uaa-service
  cloud:
    config:
      uri: http://localhost:8769
      fail-fast: true
  profiles:
      active: pro
management:
  security:
    enabled: false #報錯
           

resources檔案下其他代碼

fzp-jwt.jks

logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <include resource="org/springframework/boot/logging/logback/base.xml" />
    <logger name="org.springframework.web" level="INFO"/>

</configuration>
           

代碼

@EnableEurekaClient
           

1. entity

role

@Entity
public class Role implements GrantedAuthority {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(nullable = false)
	private String name;

	@Override
	public String getAuthority() {
		return name;
	}

	@Override
	public String toString() {
		return name;
	}
}
           

user

@Entity
public class User implements UserDetails, Serializable {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(nullable = false,  unique = true)
	private String username;

	@Column
	private String password;

	@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
			inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
	private List<Role> authorities;


	public User() {
	}

	public Long getId() {
		return id;
	}
	public void setId(Long id) {
		this.id = id;
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return authorities;
	}

	public void setAuthorities(List<Role> authorities) {
		this.authorities = authorities;
	}

}
           

2. dao 和 service

public interface UserDao extends JpaRepository<User, Long> {

	User findByUsername(String username);
}


@Service
public class UserServiceDetail implements UserDetailsService {

    @Autowired
    private UserDao userRepository;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userRepository.findByUsername(username);
    }
}
           

3. config

oauth2 config繼承 Authorization Server Configurer Adapter

@Configuration
@Enable Authorization Server //開啟 認證server
public class OAuth2Config extends Authorization Server Configurer Adapter {
    @Override //Client Details Service Configurer
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory() //記憶體 
                .withClient("uaa-service")
                .secret("123456")
                .scopes("service")
                .autoApprove(true)
                .authorizedGrantTypes("implicit","refresh_token", "password", "authorization_code") //4種都支援
                .accessTokenValiditySeconds(24*3600);//24小時過期
    }

    @Override //Authorization Server Endpoints Configurer
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
	//token Store,jwtToken enhancer
        endpoints.tokenStore(tokenStore()).tokenEnhancer(jwtTokenEnhancer()).authenticationManager(authenticationManager);
    }

    @Override//Authorization Server Security Configurer
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients()
            .passwordEncoder(NoOpPasswordEncoder.getInstance());

        /**
         * 這就是為什麼以前,可以fein,卻不可以 postMMan吧
         * 必須設定allowFormAuthenticationForClients 否則沒有辦法用postman擷取token
         * 也需要指定密碼加密方式BCryptPasswordEncoder
         */
    }

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Bean //token
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtTokenEnhancer());
    }

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        //得到 key工程
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("fzp-jwt.jks"), "fzp123".toCharArray());
        //建立 converter
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        //設定 keyPair 。注意 這個.jks,可能已經過期,這裡會報錯,重新生成
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("fzp-jwt"));
        
        return converter;
    }
}

           

resource server配置 Resource Server Configurer Adapter

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends Resource Server Configurer Adapter{
    Logger log = LoggerFactory.getLogger(ResourceServerConfiguration.class);

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests() //下面這些請求,直接放行
                .regexMatchers(".*swagger.*",".*v2.*",".*webjars.*","/user/login.*","/user/registry.*","/user/test.*",".*actuator.*").permitAll()
                .antMatchers("/**").authenticated();
//        .antMatchers("/**").permitAll();
    }

}
           

security配置 WebSecurity Configurer Adapter

@Configuration
class WebSecurityConfig extends WebSecurity Configurer Adapter {

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authentication Manager Bean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //CSRF:因為不再依賴于Cookie,是以你就不需要考慮對CSRF(跨站請求僞造)的防範。
        http
            .csrf().disable()
                .exceptionHandling()
               // .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .authenticationEntryPoint(new AuthenticationEntryPoint() {
                    @Override
                    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); //401
                    }
                })
                .and()
                .authorizeRequests()
                .antMatchers("/**").authenticated()
            .and()
                .httpBasic();
    }

    @Autowired
    UserServiceDetail userServiceDetail;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userServiceDetail)
                .passwordEncoder(new BCryptPasswordEncoder());
    }
}

           
  • UserUtils在後面指派代碼
  • feign的 /oauth/token,依然在後面複制代碼
@FeignClient(value = "uaa-service")
@PostMapping(value = "/oauth/token")
           

繼續閱讀