原贴地址: 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

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

配置

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<WebSecurity> {
//......
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

转 - spring security oauth2 password授权模式的更多相关文章

  1. Spring Security OAuth2 Demo —— 授权码模式

    本文可以转载,但请注明出处https://www.cnblogs.com/hellxz/p/oauth2_oauthcode_pattern.html 写在前边 在文章OAuth 2.0 概念及授权流 ...

  2. Spring Security OAuth2 Demo —— 密码模式(Password)

    前情回顾 前几节分享了OAuth2的流程与授权码模式和隐式授权模式两种的Demo,我们了解到授权码模式是OAuth2四种模式流程最复杂模式,复杂程度由大至小:授权码模式 > 隐式授权模式 > ...

  3. Spring Security OAuth2 Demo —— 客户端模式(ClientCredentials)

    前情回顾 前几节分享了OAuth2的流程与其它三种授权模式,这几种授权模式复杂程度由大至小:授权码模式 > 隐式授权模式 > 密码模式 > 客户端模式 本文要讲的是最后一种也是最简单 ...

  4. Spring security oauth2 password flow

    Spring security oauth2 包含以下两个endpoint来实现Authorization Server: AuthorizationEndpoint: 授权请求访问端点, 默认url ...

  5. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  6. 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证授权.鉴权的逻辑,结合 ...

  7. Spring Security OAuth2 Demo —— 隐式授权模式(Implicit)

    本文可以转载,但请注明出处https://www.cnblogs.com/hellxz/p/oauth2_impilit_pattern.html 写在前面 在文章OAuth 2.0 概念及授权流程梳 ...

  8. spring security oauth2 client_credentials模

    spring security oauth2 client_credentials模 https://www.jianshu.com/p/1c3eea71410e 序 本文主要简单介绍一下spring ...

  9. springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)

    项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖  ...

随机推荐

  1. 软件工程 week 04

    四则运算 一.摘要 作业地址:https://edu.cnblogs.com/campus/nenu/2016CS/homework/2266 git仓库地址:https://git.coding.n ...

  2. day06 内存地址 小数据池缓存机制

    1. 内存相关 示例一 v1=[11,22,33] v2=[11,22,33] #值相等 内存地址不等 v1=11 v2=11 #按理说内存地址应该不等,但是python为了优化使其内存地址相等 v1 ...

  3. spring boot 1.4 整合 mybatis druid

    http://www.jianshu.com/p/cef49ad91ba9spring boot 1.4 整合 mybatis druid

  4. python set 集合复习--点滴

    一.set特性: set是一个无序不重复的元素集合. 集合对象是一组无序排列的可哈希的值,集合成员可以做字典中的键.集合支持用in和not in操作符检查成员,由len()内建函数得到集合的基数(大小 ...

  5. PythonStudy——格式化输入小练习

    # 练习:用户输入姓名.年龄.工作.爱好 ,然后打印成以下格式# ------------ info of Egon -----------# Name : Egon# Age : 22# Sex : ...

  6. python调用mediainfo工具批量提取视频信息

    写了2个脚本,分别是v1版本和v2版本 都是python调用mediainfo工具提取视频元数据信息 v1版本是使用pycharm中测试运行的,指定了视频路径 v2版本是最终交付给运营运行的,会把v2 ...

  7. 十九、springcloud(五)配置中心本地示例和refresh

    1.创建spring-cloud-houge-config子项目,测试需要的项目入下 2.添加依赖 <dependency> <groupId>org.springframew ...

  8. CentOS 7下给nginx安装SSL证书

    0. DNS要能解析你的网址(域名解析和主机解析,例如example.com和www.example.com都要能解析.注意泛解析记录*.example.com可以存在但在本文中暂时无法用于https ...

  9. 华硕飞马3S,日常使用续航测试

    最近爱机荣耀6的电池1天2充,无奈换台新机,华为系列没大电池且价格贵,小米红米系列品控呵呵,其他品牌无小屏幕大容量电池: 然后换了台华硕飞马3S:5.2英寸 5000ma电池,日常工作娱乐使用1天半多 ...

  10. android 使用Retrofit2 RxJava 文件上传

    private static void upload(final Context context, final int type, File logFile) { Map<String, Req ...