Spring Cloud Security

来源:互联网 发布:mac .m2 文件夹在哪里 编辑:程序博客网 时间:2024/06/05 13:31

发博词

知识点

  1. 封装顺序是这样的:spring security及其各个模块=》spring cloud security=》spring boot autoconfigure的security部分,比如autoconfigure模块有个spring security的sso,是对spring security在oath2下的封装,
  2. spring oauth2 authorizeserver,resourceserver,认证服务器和资源服务器是怎么交互的,token_key,/oauth/token/ refresh/token,resourceserver就是业务系统,oauth client 就是边缘业务系统,比如直接面向用户的UI系统,或者UI系统直接调用的API接口这一层;
  3. JWT和OAuth2的区别?看到好多人在比较这两个东西,现在终结这个问题:JWT只是OAuth2中的token的一种类型。
  4. jwt client(Resource Server或者Zuul等),使用jwt的业务系统在解码acces_token的时候,需要一个toke_key,这个token-key就是JWT Client应用启动的时候从Auth Server拉取的,接口是token/token_key
  5. 单点登录这种功能,好多javaee容器都自带的,像websphere
  6. spring Security完全将认证和授权分开了,资源只需要声明自己是需要认证的,需要什么样的权限,只管跟当前用户要access_token。授权的四种方式任意,只要拿到token就可以去让资源去认证。
  7. 边缘服务器需要开启@EnableOAuth2Sso,但是边缘服务器也是一个ResourceServer,边缘服务器如果是zuul的话,就不是一个ResourceServer了,只需要添加@EnableOAuth2Sso注解就可以了;
  8. client_credentials模式下spring boot不会帮助spring Security构建ClientCredentialsResourceDetails 对象,需要开发者自己创建
  9. favicon.icon,记得把这个东西过滤掉,奶奶的
  10. 在其中一个边缘服务上,您可能需要启用单点登录。 @EnableOAuthSso,只需要在边缘服务器指定没用来引导未登录的用户登录系统。@EnableOAuthSso将允许您将未经认证的用户的自动重定向转向授权服务器,他们将能够登录
  11. EnableOAuth2Client,在中间中继的时候用
  12. ClientCredentialsTokenEndpointFilter,AS设置了allowFormAuthenticationForClients才会有,详情看这里面的AuthorizationServerSecurityConfigurer#configure(HttpSecurity http)逻辑,这点非常重要,ClientCredentialsTokenEndpointFilter是用来验证clientid和client_secret的,使用clientid和client_secret换取下一步的东西;
  13. TokenGranter,AuthorizationCodeTokenGranter,ClientCredentialsTokenGranter,RefreshTokenGranter,ImplicitTokenGranter,ResourceOwnerPasswordTokenGranter
  14. TokenServices分为两类,一个是用在AuthenticationServer端,AuthorizationServerTokenServices,ResourceServer端有自己的tokenServices接口,
  15. BearerTokenExtractor,从其可以看出,token的获取顺序,Header,parameters(get/post)
  16. spring security 保护自己的配置,作为ResourceServer的权限配置和作为AuthorizationServer的配置都是在不同的地方
  17. An OAuth 2 authentication token can contain two authentications: one for the client(OAuth2 Client) and one for the user. Since some OAuth authorization grants don’t require user authentication, the user authentication may be null.
  18. jwt是不需要存储access_toen的,jwt的机制就是将所有的信息都存在了token里面,从JwtTokenStore也可以看出来
  19. OAuth2AuthenticationManager是密切与token认证相关的,而不是与获取token密切相关的。这是真正认证的地方,一会重点debug,resourceIds
  20. 每一个ResourceServer在配置的时候,ResourceServerConfiguration,需要配置一个resourceID,一个ResourceServer只能配置一个
  21. oauth/token = 先验证的是clientid和clientsecret,接着在验证username和userpassword,都是用的ProvideManager,两次验证是两个不同的请求,oauth2客户端会使用RestTemplate请求服务器的接口
  22. ClientCredentialsTokenEndpointFilter用来验证clientId和clientsecret的:
    OAuth2ClientAuthenticationProcessingFilter:OAuth2客户端用来从OAuth2认证服务器获取access token,也可以从OAuth2认证服务器加载authentication对象到OAuth2客户端的SecurityContext对象中;里面调用OAuth2AuthenticationManager#authenticate()方法使用DefaultTokenServices ,DefaultTokenServices 使用JwtTokenStore,JwtTokenStore使用JwtAccessTokenConverter来将JWT解密成Auth对象。 来从AuthServer请求授权信息
  23. accessToken被解密成如下的JWT对象:
    {“alg”:”RS256”,”typ”:”JWT”} {“exp”:1503758022,”user_name”:”admin”,”authorities”:[“ROLE_TRUSTED_CLIENT”,”ROLE_ADMIN”,”ROLE_USER”],”jti”:”d56f43d2-6c4a-46cf-85f3-050ee195a2bd”,”client_id”:”confidential”,”scope”:[“read”]} [128 crypto bytes]
  24. AbstractSecurityInterceptor#befroeInvaction 是ResourceServer获取认证信息的地方
  25. 只要是需要验证token有效性的都需要jwt.key-uri的配置
  26. AffirmativeBased值得debug

TIPS

@Override    public void configure(WebSecurity web) throws Exception {        web.ignoring().antMatchers("/favicon.ico");    }    @Bean    @Override    protected UserDetailsService userDetailsService(){        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();        manager.createUser(User.withUsername("user").password("password").roles("USER").authorities("USER").build());        manager.createUser(User.withUsername("admin").password("password").roles("USER", "ADMIN", "TRUSTED_CLIENT").authorities("USER").build());        return manager;    }

这两种方式有差别,牵扯到UsernamePasswordAuthenticationFilter和ClientCredentialsTokenEndpointFilter

security:   oauth2:    client:      client-id: confidential      client-secret: secret      access-token-uri: http://localhost:8080/oauth/token      user-authorization-uri: http://localhost:8080/oauth/authorize      use-current-uri: true    resource:       jwt:        key-uri: http://localhost:8080/oauth/token_key      filter-order: 3  

client里面的配置最终是用来生成OAuth2ProtectedResourceDetails的bean的,参看OAuth2ProtectedResourceDetailsConfiguration

几个注解

@EnableOAuth2Sso or @EnableOAuth2Client
1. EnableOAuth2Sso
OAuth2ClientAuthenticationProcessingFilter
ResourceServer配置
2. EnableOAuth2Client
OAuth2ClientContextFilter

配置分解

Authorization Server
security.oauth2.client.client-id和security.oauth2.client.client-secret,用于设置一对ResourceServer 用来认证的Authorization Server的clientid和client secret
security.oauth2.client.client-authentication-scheme:form/header/none/query

ResourceServer
security.oauth2.resource.user-info-uri:userinfo的url地址
security.oauth2.resource.token-info-uri:check token的url地址
security.oauth2.resource.token-type: 设置token type ,比如Bearer

如果token类型是jwt的话:
security.oauth2.resource.jwt.key-value:symmetric secret or PEM-encoded RSA public key
security.oauth2.resource.jwt.key-uri:获取key的地址

sso:
security.oauth2.sso.login-path
security.oauth2.sso.filter-order

四种授权模式下的Filters

这么操作

Spring Cloud Security一共有两个starter:

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

这两个starter牵扯到三个具体的实现:

<dependency>    <groupId>org.springframework.security.oauth</groupId>    <artifactId>spring-security-oauth2</artifactId></dependency><dependency>    <groupId>org.springframework.security</groupId>    <artifactId>spring-security-jwt</artifactId></dependency><dependency>    <groupId>org.springframework.cloud</groupId>    <artifactId>spring-cloud-security</artifactId>    <version>${project.version}</version></dependency>

前两个属于Spring Security的体系架构,第三个是对feign和zuul做了封装。

Spring Cloud Security

spring cloud Security主要的任务是为spring cloud 中的各个组件提供token的中继功能,zuul,feign,RestTemplate

Token中继

token 中继有几种类型,请求产生新的请求时,将access_token的值传递过去,这样被请求的被保护的资源就不用再去authorize server上获取新的access_token了;

Client Token Relay

Client Token Relay in Zuul Proxy

OAuth2TokenRelayFilter,一个pre类型的ZuulFilter,extracts an access token from the currently authenticated user, and puts it in a request header for the downstream requests.
AuthenticationHeaderFilter,一个pre类型的ZuulFilter。
ZuulFilter将自己收到的请求里的access_token提取出来,放到请求service时的请求的header里

一个牛逼的功能

proxy:  auth:    routes:      customers: oauth2      stores: passthru      recommendations: none

可以为每一个代理设置授权方式。

Resource Server Token Relay(Feign)

OAuth2FeignRequestInterceptor,在header里添加token,token是从AuthorizationServer获取的。

DEMO

ResourceServer中继成功:
被调用的ResourceServer上的OAuth2AuthenticationProcessingFilter,抽取请求里的header的bear access_token信息,并转换为Authentication成功 Authentication authentication = tokenExtractor.extract(request);
Zuul+ResourceServer中继成功
代理了两个微服务,调用其中一个服务授权流程走完,调用另一个服务时,已经授权,直接返回调用信息
Client中继成功
可以走完授权流程,调用成功

常见问题

问题1
Possible CSRF detected - state parameter was required but no state could be found
答:code重复使用,也就是不停刷新授权后的界面导致的
https://github.com/spring-projects/spring-security-oauth/issues/322 这个issue解决了问题

参考

使用OAuth2的SSO分析
使用JWT的OAuth2的SSO分析
Spring Cloud Security
使用 OAuth 2 和 JWT 为微服务提供安全保障
OAuth 2和JWT - 如何设计安全的API?
How to use JWT and OAuth with Spring Boot
Advanced Microservices Security with Spring and OAuth2
使用zuul及oauth2构建api网关实践之路
zuul 做权限服务的时候大家是用自定义的ZuulFilter + jwt 去做还是用spring-security-oauth2 去做的
spring cloud单点登录
OAuth 2 Developers Guide
Spring Cloud:Eureka,Zuul和OAuth2 - 扩展授权服务器
FeignClient 在 oauth2 中与 hystrix 线程策略冲突问题造成的权限问题
feign-oauth2-spring-cloud-starter

原创粉丝点击