Spring Cloud 基于OAth2协议与JWT搭建一个简易网关

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

    网上有很多与此类型相似的文章,但是在我搭建网关集成认证功能时,要么参考的这些文章并不全,要么不是我想要的或者说是比较复杂。因此本篇将会搭建一个简易的网关服务,采用oauth2协议的passowrd模式来进行身份认证,jwt作为token令牌。最终达到需要登录获取AccessToken才能向网关申请服务资源的效果。本篇博文代码已托管至码云。

    项目整体的目录结构如下

153622_nZcY_3773384.png

    版本:Spring Cloud Edgware.SR3

              Spring Boot 1.5.12.RELEASE

    1.首先创建父工程

    pom.xml部分如下

    UTF-8UTF-81.8Edgware.SR31.5.12.RELEASEorg.springframework.bootspring-boot-starter-actuatororg.springframework.bootspring-boot-starter-testtestorg.springframework.cloudspring-cloud-starter-eurekaorg.springframework.cloudspring-cloud-dependencies${spring.cloud.version}pomimportspring-milestonesSpring Milestoneshttps://repo.spring.io/libs-milestonefalse

    2.搭建Eureka服务治理

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {public static void main(String[] args) {SpringApplication.run(EurekaServerApplication.class, args);}
}

    3.搭建一个示例资源服务

    提供/test端点用于测试

@RestController
@EnableEurekaClient
@SpringBootApplication
public class ResourceServiceApplication {public static void main(String[] args) {SpringApplication.run(ResourceServiceApplication.class, args);}@GetMapping("/test")public String testAuthentication() {return "authentication permit";}
}

    4.搭建认证服务

    用到如下依赖

org.springframework.cloudspring-cloud-starter-oauth2

    认证服务配置

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate UserDetailsService userDetailsService;@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//使用内存存储clients.inMemory()//分配客户端账号.withClient("client").secret("client-secret")//支持的授权类型.authorizedGrantTypes("refresh_token", "password").scopes("server")//token有效时长.accessTokenValiditySeconds(1200)//refreshToken有效时长.refreshTokenValiditySeconds(50000);}@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();//设置签名密钥jwtAccessTokenConverter.setSigningKey("demo");return jwtAccessTokenConverter;}//使用JWT作为token@Beanpublic TokenStore jwtTokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter()).reuseRefreshTokens(true)//配置以生效password模式.authenticationManager(authenticationManager).userDetailsService(userDetailsService);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");}
}

    注意:这里需要配置authenticationManager否则无法支持password模式。当获取token时,出现如下响应。

{"error": "unsupported_grant_type","error_description": "Unsupported grant type: password"
}

    安全服务配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserDetailsService userDetailsService;@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin().and().authorizeRequests().anyRequest().authenticated().and().csrf().disable();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());}
}

    简单模拟用户校验服务

@Component
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate PasswordEncoder passwordEncoder;//username:任意 password:123456@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {return new User(username, passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));}
}

    application.yml

spring:application:name: auth-server
server:port: 4040
security:oauth2:resource:filter-order: 3
management:security:enabled: false
eureka:client:service-url:defaultZone: http://eureka:pwd@localhost:8761/eureka

    5.搭建服务网关

    资源服务配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests()//去掉获取token会被拦截.antMatchers("/auth/**").permitAll().anyRequest().authenticated();}
}

    注意:这里需要放行/auth/**否则网关会在获取token请求时就对其身份进行校验拦截

    添加网关过滤器

@Component
public class AuthFilter extends ZuulFilter {//拦截类型@Overridepublic String filterType() {return PRE_TYPE;}//拦截顺序@Overridepublic int filterOrder() {return SERVLET_DETECTION_FILTER_ORDER - 1;}//开启拦截@Overridepublic boolean shouldFilter() {return true;}//拦截处理逻辑@Overridepublic Object run() {//获取用户认证信息Authentication authentication = SecurityContextHolder.getContext().getAuthentication();System.out.println(authentication);return null;}
}

    application.yml

spring:application:name: api-gateway
server:port: 8040
eureka:client:service-url:defaultZone: http://eureka:pwd@localhost:8761/eureka
zuul:ignoredServices: '*'routes:resource-service: /demo/**auth-server: /auth/**sensitive-headers:management:security:enabled: falsesecurity:oauth2:client://在认证服务器中配置的客户端账号clientId: clientclientSecret: client-secretresource:token-info-uri: http://localhost:4040/oauth/check_tokenprefer-token-info: truejwt:key-uri: http://localhost:4040/oauth/token_keysessions: stateless

    注意:由于使用token-info-uri,因此需先启动auth-server再启动网关服务,因为网关服务在启动时会调用该端点获取数据。如先启动网关会出现如下报错日志。

I/O error on GET request for "http://localhost:4040/oauth/token_key": Connection refused: connect;
nested exception is java.net.ConnectException: Connection refused: connect

    至此,一个简单的网关认证服务就搭建完成了。接下来,让我们来测试一下。

    直接通过网关代理请求测试端点,返回结果如下,响应提示需要认证后才可访问资源。

155742_VX5B_3773384.png

    password模式获取jwt token

155944_92Xf_3773384.png

    通过获取到的access_token请求资源服务

160023_a8jY_3773384.png

    控制台可见如下输出,可见在过滤器获取到了用户的身份信息

org.springframework.security.oauth2.provider.OAuth2Authentication@407c5f9d: Principal: user;
Credentials: [PROTECTED]; Authenticated: true; Details: remoteAddress=0:0:0:0:0:0:0:1,
tokenType=BearertokenValue=; Granted Authorities: ROLE_USER

    本篇博文从PIG项目中简化剥离出来,如有需要进一步拓展的小伙伴们,推荐两个开源项目

    冷冷——PIG

    老A——AG-Admin(好像换人维护了)

转载于:https://my.oschina.net/u/3773384/blog/1802283


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部