开源框架-SpringCloud系列SpringCloudSpring Coud

springcloud oauth2 jwt gateway d

2019-12-22  本文已影响0人  _Rondo
前言

前几天不是写了个没有网关的微服务授权中心吗,今天终于看明白了,是我代理做的少,一直以为/api/** 到服务器上也是 api-service/api/**,结果打开security debug 才发现他请求根本匹配不到,而且被gateway转发还有个去除前缀的问题,我又做了个简单的demo,这里贴下关键代码,用的内存模式,可以参照上一篇改成jdbc模式

示例

uaa 认证服务

@Configuration
@EnableAuthorizationServer
@AllArgsConstructor
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("user-service")
                .secret("123456")
                .scopes("service")
                .autoApprove(true)
                .authorizedGrantTypes("implicit", "refresh_token", "password", "authorization_code")
                .accessTokenValiditySeconds(12 * 300);//5min过期
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).tokenEnhancer(jwtTokenEnhancer()).authenticationManager(authenticationManager);
    }

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

        /**
         * 必须设置allowFormAuthenticationForClients 否则没有办法用postman获取token
         * 也需要指定密码加密方式BCryptPasswordEncoder
         */
    }

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

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

    @Bean
    protected JwtAccessTokenConverter jwtTokenEnhancer() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setKeyPair(keyPair());
        return jwtAccessTokenConverter;
    }

    @Bean
    public KeyPair keyPair() {
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("demojwt.jks"), "keystorepass".toCharArray());
        return keyStoreKeyFactory.getKeyPair("jwt", "keypairpass".toCharArray());
    }

uaa websecurityconfig

@Configuration
class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .exceptionHandling()
                .authenticationEntryPoint((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and()
                .authorizeRequests()
                .antMatchers("/.well-known/jwks.json").permitAll()
                .antMatchers("/**").authenticated()
                .and()
                .httpBasic();
    }

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

资源服务配置

@EnableWebFluxSecurity
public class SecurityConfig {
    @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws Exception {
        http
                .authorizeExchange()
                .pathMatchers("/**").authenticated()
                .anyExchange()
                .authenticated()
                .and()
                .oauth2ResourceServer()
                .jwt();
        return http.build();
    }
}

网关配置

@SpringBootApplication
@EnableEurekaClient
public class GatewayServiceApplication {


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

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("resource", r -> r.path("/resource/**")
                        .filters(f -> f.stripPrefix(1))//去掉第一层前缀如果是/api/oauth这种 就stripPrefix(2)
                        .uri("lb://resource-service")) // Prevents cookie being sent downstream
//                        .uri("http://localhost:9090")) // Taking advantage of docker naming
                .route("uaa",r -> r.path("/uaa/**")
                        .filters(f -> f.stripPrefix(1))
                        .uri("lb://uaa-service"))
                .build();
    }
}

演示

直接授权
http://localhost:9999/oauth/token?client_id=user-service&client_secret=123456&grant_type=password&username=wenx&password=admin

image.png
访问开放资源
http://localhost:9090/hello
image.png
访问需要授权
image.png
带上token访问
image.png
经过网关转发授权
http://localhost:8068/uaa/oauth/token?client_id=user-service&client_secret=123456&grant_type=password&username=wenx&password=admin
image.png
经过网关访问开发资源
http://localhost:8068/resource/hello
image.png

经过网关访问授权资源
http://localhost:8068/resource/foo

image.png
带上token访问授权资源
http://localhost:8068/resource/foo
image.png

项目地址 >>> https://github.com/Chaimouren/auth-gateway
-end-

上一篇 下一篇

猜你喜欢

热点阅读