oauth password模式_转 - spring security oauth2 password授权模式

原贴地址: https://segmentfault.com/a/1190000012260914#articleHeader6

前面的一篇文章讲了spring security oauth2的client credentials授权模式,一般用于跟用户无关的,开放平台api认证相关的授权场景。本文主要讲一下跟用户相关的授权模式之一password模式。

回顾四种模式

OAuth 2.0定义了四种授权方式。

授权码模式(authorization code)

简化模式(implicit)

密码模式(resource owner password credentials)

客户端模式(client credentials)(主要用于api认证,跟用户无关)

maven

org.springframework.security.oauth

spring-security-oauth2

org.springframework.boot

spring-boot-starter-security

配置

security config

支持password模式要配置AuthenticationManager

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class SecurityConfig extends WebSecurityConfigurerAdapter {

//需要正常运行的话,需要取消这段注释,原因见下面小节

// @Override

// public void configure(HttpSecurity http) throws Exception {

// http.csrf().disable();

// http.requestMatchers().antMatchers("/oauth/**")

// .and()

// .authorizeRequests()

// .antMatchers("/oauth/**").authenticated();

// }

//配置内存模式的用户

@Bean

@Override

protected UserDetailsService userDetailsService(){

InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

manager.createUser(User.withUsername("demoUser1").password("123456").authorities("USER").build());

manager.createUser(User.withUsername("demoUser2").password("123456").authorities("USER").build());

return manager;

}

/**

* 需要配置这个支持password模式

* support password grant type

* @return

* @throws Exception

*/

@Override

@Bean

public AuthenticationManager authenticationManagerBean() throws Exception {

return super.authenticationManagerBean();

}

}

这个是比client credentials模式新增的配置,主要配置用户以及authenticationManager

auth server配置

@Configuration

@EnableAuthorizationServer //提供/oauth/authorize,/oauth/token,/oauth/check_token,/oauth/confirm_access,/oauth/error

public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {

@Override

public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

oauthServer

.tokenKeyAccess("permitAll()") //url:/oauth/token_key,exposes public key for token verification if using JWT tokens

.checkTokenAccess("isAuthenticated()") //url:/oauth/check_token allow check token

.allowFormAuthenticationForClients();

}

/**

* 注入authenticationManager

* 来支持 password grant type

*/

@Autowired

private AuthenticationManager authenticationManager;

@Override

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

endpoints.authenticationManager(authenticationManager);

}

@Override

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

clients.inMemory()

.withClient("demoApp")

.secret("demoAppSecret")

.authorizedGrantTypes("client_credentials", "password", "refresh_token")

.scopes("all")

.resourceIds("oauth2-resource")

.accessTokenValiditySeconds(1200)

.refreshTokenValiditySeconds(50000);

}

这里记得注入authenticationManager来支持password模式

否则报错如下

➜ ~ curl -i -X POST -d "username=demoUser1&password=123456&grant_type=password&client_id=demoApp&client_secret=demoAppSecret" http://localhost:8080/oauth/token

HTTP/1.1 400

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Frame-Options: DENY

X-Application-Context: application

Cache-Control: no-store

Pragma: no-cache

Content-Type: application/json;charset=UTF-8

Transfer-Encoding: chunked

Date: Sun, 03 Dec 2017 07:01:27 GMT

Connection: close

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

resource server 配置

@Configuration

@EnableResourceServer

public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

// /**

// * 要正常运行,需要反注释掉这段,具体原因见下面分析

// * 这里设置需要token验证的url

// * 这些需要在WebSecurityConfigurerAdapter中排查掉

// * 否则优先进入WebSecurityConfigurerAdapter,进行的是basic auth或表单认证,而不是token认证

// * @param http

// * @throws Exception

// */

// @Override

// public void configure(HttpSecurity http) throws Exception {

// http.requestMatchers().antMatchers("/api/**")

// .and()

// .authorizeRequests()

// .antMatchers("/api/**").authenticated();

// }

}

验证

请求token

curl -i -X POST -d "username=demoUser1&password=123456&grant_type=password&client_id=demoApp&client_secret=demoAppSecret"http://localhost:8080/oauth/token

返回

HTTP/1.1 200

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Frame-Options: DENY

X-Application-Context: application

Cache-Control: no-store

Pragma: no-cache

Content-Type: application/json;charset=UTF-8

Transfer-Encoding: chunked

Date: Sun, 03 Dec 2017 04:53:40 GMT

{"access_token":"4cfb16f9-116c-43cf-a8d4-270e824ce5d7","token_type":"bearer","refresh_token":"8e9bfbda-77e5-4d97-b061-4e319de7eb4a","expires_in":1199,"scope":"all"}

携带token访问资源

curl -i http://localhost:8080/api/blog/1\?access_token\=4cfb16f9-116c-43cf-a8d4-270e824ce5d7

或者

curl -i -H "Accept: application/json" -H "Authorization: Bearer 4cfb16f9-116c-43cf-a8d4-270e824ce5d7" -X GET http://localhost:8080/api/blog/1

返回

HTTP/1.1 302

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Frame-Options: DENY

Set-Cookie: JSESSIONID=F168A54F0F3C3D96A053DB0CFE129FBF; Path=/; HttpOnly

Location: http://localhost:8080/login

Content-Length: 0

Date: Sun, 03 Dec 2017 05:20:19 GMT

出错原因见下一小结

成功返回

HTTP/1.1 200

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Frame-Options: DENY

X-Application-Context: application

Content-Type: text/plain;charset=UTF-8

Content-Length: 14

Date: Sun, 03 Dec 2017 06:39:24 GMT

this is blog 1

错误返回

HTTP/1.1 401

X-Content-Type-Options: nosniff

X-XSS-Protection: 1; mode=block

Cache-Control: no-cache, no-store, max-age=0, must-revalidate

Pragma: no-cache

Expires: 0

X-Frame-Options: DENY

Cache-Control: no-store

Pragma: no-cache

WWW-Authenticate: Bearer realm="oauth2-resource", error="invalid_token", error_description="Invalid access token: 466ee845-2d08-461b-8f62-8204c47f652"

Content-Type: application/json;charset=UTF-8

Transfer-Encoding: chunked

Date: Sun, 03 Dec 2017 06:39:28 GMT

{"error":"invalid_token","error_description":"Invalid access token: 466ee845-2d08-461b-8f62-8204c47f652"}

WebSecurityConfigurerAdapter与ResourceServerConfigurerAdapter

二者都有针对http security的配置,他们的默认配置如下

WebSecurityConfigurerAdapter

spring-security-config-4.2.3.RELEASE-sources.jar!/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.java

@Order(100)

public abstract class WebSecurityConfigurerAdapter implements

WebSecurityConfigurer {

//......

protected void configure(HttpSecurity http) throws Exception {

logger.debug("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity).");

http

.authorizeRequests()

.anyRequest().authenticated()

.and()

.formLogin().and()

.httpBasic();

}

//......

}

可以看到WebSecurityConfigurerAdapter的order是100

ResourceServerConfigurerAdapter

spring-security-oauth2-2.0.14.RELEASE-sources.jar!/org/springframework/security/oauth2/config/annotation/web/configuration/ResourceServerConfigurerAdapter.java

public void configure(HttpSecurity http) throws Exception {

http.authorizeRequests().anyRequest().authenticated();

}

它的order是SecurityProperties.ACCESS_OVERRIDE_ORDER - 1

spring-boot-autoconfigure-1.5.5.RELEASE-sources.jar!/org/springframework/boot/autoconfigure/security/oauth2/resource/ResourceServerProperties.java

/**

* The order of the filter chain used to authenticate tokens. Default puts it after

* the actuator endpoints and before the default HTTP basic filter chain (catchall).

*/

private int filterOrder = SecurityProperties.ACCESS_OVERRIDE_ORDER - 1;

由此可见WebSecurityConfigurerAdapter的拦截要优先于ResourceServerConfigurerAdapter

二者关系

WebSecurityConfigurerAdapter用于保护oauth相关的endpoints,同时主要作用于用户的登录(form login,Basic auth)

ResourceServerConfigurerAdapter用于保护oauth要开放的资源,同时主要作用于client端以及token的认证(Bearer auth)

因此二者是分工协作的

在WebSecurityConfigurerAdapter不拦截oauth要开放的资源

@Override

public void configure(HttpSecurity http) throws Exception {

http.csrf().disable();

http.requestMatchers().antMatchers("/oauth/**")

.and()

.authorizeRequests()

.antMatchers("/oauth/**").authenticated();

}

在ResourceServerConfigurerAdapter配置需要token验证的资源

@Override

public void configure(HttpSecurity http) throws Exception {

http.requestMatchers().antMatchers("/api/**")

.and()

.authorizeRequests()

.antMatchers("/api/**").authenticated();

}

这样就大功告成

doc

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值