oauth2 access_denied 不允许访问_OAuth2.0系列之密码模式实践教程(四)

本文是OAuth2.0系列教程的第四篇,主要讲解了密码模式的概念、授权流程,并提供了实践示例,包括实验环境准备、OAuth2.0角色解析、配置类设置以及功能测试。
摘要由CSDN通过智能技术生成

OAuth2.0系列之密码模式实践教程(四)

    • 1、密码模式简介

      • 1.1 前言简介

      • 1.2 授权流程图

    • 2、例子实践

      • 2.1 实验环境准备

      • 2.2 OAuth2.0角色

      • 2.3 OAuth2.0配置类

      • 2.4 Security配置类

      • 2.5 功能简单测试


OAuth2.0系列博客:

  • OAuth2.0系列之基本概念和运作流程(一)

  • OAuth2.0系列之授权码模式实践教程(二)

  • OAuth2.0系列之简化模式实践教程(三)

  • OAuth2.0系列之密码模式实践教程(四)

  • OAuth2.0系列之客户端模式实践教程(五)

  • OAuth2.0系列之信息数据库存储教程(六)

  • OAuth2.0系列之信息Redis存储教程(七)

  • OAuth2.0系列之JWT令牌实践教程(八)

  • OAuth2.0系列之集成JWT实现单点登录

1、密码模式简介

1.1 前言简介

在上一篇文章中我们学习了OAuth2的一些基本概念,对OAuth2有了基本的认识,接着学习OAuth2.0授权模式中的密码模式

ps:OAuth2.0的授权模式可以分为:

  • 授权码模式(authorization code)

  • 简化模式(implicit)

  • 密码模式(resource owner password credentials)

  • 客户端模式(client credentials)

密码模式(resource owner password credentials):密码模式中,用户向客户端提供自己的用户名和密码,这通常用在用户对客户端高度信任的情况

1.2 授权流程图

官网图片:20571a61d960dd76964e11bdea42cd54.png

  • (A)用户访问客户端,提供URI连接包含用户名和密码信息给授权服务器

  • (B)授权服务器对客户端进行身份验证

  • (C)授权通过,返回acceptToken给客户端

从调接口方面,简单来说:

  • 第一步:直接传username,password获取token

http://localhost:8888/oauth/token?client_id=cms&client_secret=secret&username=admin&password=123456&grant_type=password&scope=all

  • 第二步:拿到acceptToken之后,就可以直接访问资源

http://localhost:8084/api/userinfo?access_token=${accept_token}

2、例子实践

2.1 实验环境准备

  • IntelliJ IDEA

  • Maven3.+版本
    新建SpringBoot Initializer项目,可以命名passwordb87e325998cc88a9fd4919a675f07742.png

59b4399f69260c2c618f2c12df0d2d74.png
主要是想引入:

 <dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>

<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-oauth2artifactId>
dependency>

<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-securityartifactId>
dependency>

2.2 OAuth2.0角色

前面的学习,我们知道了OAuth2.0主要包括如下角色,下面通过代码例子加深对理论的理解

  • 资源所有者(Resource Owner)

  • 用户代理(User Agent)

  • 客户端(Client)

  • 授权服务器(Authorization Server)

  • 资源服务器(Resource Server)

生产环境、资源服务器和授权服务器一般是分开的,不过学习的可以放在一起

定义资源服务器,用注解@EnableResourceServer;
定义授权服务器,用注解@EnableAuthorizationServer;

2.3 OAuth2.0配置类

package com.example.oauth2.password.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;


/**
*

* OAuth2.0配置类
*

*
*

* @author mazq
* 修改记录
* 修改后版本: 修改人: 修改日期: 2020/06/11 11:00 修改内容:
*

*/
@Configuration
//开启授权服务
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {

@Autowired
private AuthenticationManager authenticationManager;

private static final String CLIENT_ID = "cms";
private static final String SECRET_CHAR_SEQUENCE = "{noop}secret";
private static final String SCOPE_READ = "read";
private static final String SCOPE_WRITE = "write";
private static final String TRUST = "trust";
private static final String USER ="user";
private static final String ALL = "all";
private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 2*60;
private static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 2*60;
// 密码模式授权模式
private static final String GRANT_TYPE_PASSWORD = "password";
//授权码模式
private static final String AUTHORIZATION_CODE = "authorization_code";
//refresh token模式
private static final String REFRESH_TOKEN = "refresh_token";
//简化授权模式
private static final String IMPLICIT = "implicit";
//指定哪些资源是需要授权验证的
private static final String RESOURCE_ID = "resource_id";

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
// 使用内存存储
.inMemory()
//标记客户端id
.withClient(CLIENT_ID)
//客户端安全码
.secret(SECRET_CHAR_SEQUENCE)
//为true 直接自动授权成功返回code
.autoApprove(true)
.redirectUris("http://127.0.0.1:8084/cms/login") //重定向uri
//允许授权范围
.scopes(ALL)
//token 时间秒
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
//刷新token 时间 秒
.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS)
//允许授权类型
.authorizedGrantTypes(GRANT_TYPE_PASSWORD );
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 使用内存保存生成的token
endpoints.authenticationManager(authenticationManager).tokenStore(memoryTokenStore());
}

/**
* 认证服务器的安全配置
*
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
//.realm(RESOURCE_ID)
// 开启/oauth/token_key验证端口认证权限访问
.tokenKeyAccess("isAuthenticated()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()")
//允许表单认证
.allowFormAuthenticationForClients();
}

@Bean
public TokenStore memoryTokenStore() {
// 最基本的InMemoryTokenStore生成token
return new InMemoryTokenStore();
}

}



2.4 Security配置类

为了测试,可以进行简单的SpringSecurity

package com.example.oauth2.password.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
*

* SpringSecurity配置类
*

*
*

* @author mazq
* 修改记录
* 修改后版本: 修改人: 修改日期: 2020/06/11 11:23 修改内容:
*

*/
@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication()
auth.inMemoryAuthentication()
.withUser("nicky")
.password("{noop}123")
.roles("admin");
}

@Override
public void configure(WebSecurity web) throws Exception {
//解决静态资源被拦截的问题
web.ignoring().antMatchers("/asserts/**");
web.ignoring().antMatchers("/favicon.ico");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http // 配置登录页并允许访问
//.formLogin().permitAll()
// 配置Basic登录
//.and().httpBasic()
// 配置登出页面
.logout().logoutUrl("/logout").logoutSuccessUrl("/")
// 配置允许访问的链接
.and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**","/api/**").permitAll()
// 其余所有请求全部需要鉴权认证
.anyRequest().authenticated()
// 关闭跨域保护;
.and().csrf().disable();
}

}


2.5 功能简单测试

接口测试,要用POST方式,在postman测试,response_type参数传password:

http://localhost:8888/oauth/token?password=123&grant_type=password&username=nicky&scope=all

bf2284bfd19bc1132b9b588b0cbc0296.png

注意配置一下请求头的授权参数,username即client_id,password即client_secretcef21769937d4afd1679104dae90df29.png

代码方式请求,可以进行如下封装,即进行base64加密

HttpHeaders headers = new HttpHeaders();
byte[] key = (clientId+":"+clientSecret).getBytes();
String authKey = new String(Base64.encodeBase64(key));
LOG.info("Authorization:{}","Basic "+authKey);
headers.add("Authorization","Basic "+authKey);

拿到token直接去调业务接口:
http://localhost:8888/api/userinfo?access_token=61b113f3-f1e2-473e-a6d7-a0264bfdfa8d

例子代码下载:code download

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值