OAuth2.0介绍

OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。OAuth2.0是OAuth协议的延续版本,但不向后兼容OAuth 1.0即完全废止了OAuth1.0。很多大公司如Google,Yahoo,Microsoft等都提供了OAUTH认证服务,这些都足以说明OAUTH标准逐渐成为开放资源授权的标准。

Oauth协议目前发展到2.0版本,1.0版本过于复杂,2.0版本已得到广泛应用。

参考:https://baike.baidu.com/item/oAuth/7153134
Oauth协议:https://tools.ietf.org/html/rfc6749

spring-cloud-starter-oauth2

spring-cloud-starter-oauth2 是对OAuth2的一种实现,并且跟我们之前学习的Spring Security相辅相成,与Spring Cloud体系的集成也非常便利,接下来,我们需要对它进行学习,最终使用它来实现我们设计的分布式认证授权解决方案。

OAuth2.0的服务提供方涵盖两个服务,即授权服务 (Authorization Server,也叫认证服务) 和资源服务 (Resource Server),使用 spring-cloud-starter-oauth2 的时候你可以选择把它们在同一个应用程序中实现,也可以选择建立使用同一个授权服务的多个资源服务。

认证授权服务 (Authorization Server) 应包含对接入端以及登入用户的合法性进行验证并颁发token等功能,对令牌的请求端点由 Spring MVC 控制器进行实现,下面是配置一个认证服务必须要实现的endpoints:

AuthorizationEndpoint 服务于认证请求。默认 URL: /oauth/authorize 。
TokenEndpoint 服务于访问令牌的请求。默认 URL: /oauth/token 。

资源服务 (Resource Server) 应包含对资源的保护功能,对非法请求进行拦截,对请求中token进行解析鉴权等,下面的过滤器用于实现 OAuth 2.0 资源服务:
OAuth2AuthenticationProcessingFilter 用来对请求给出的身份令牌解析鉴权。

环境搭建

创建 spring-cloud-starter-oauth2 父工程,依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.cyj</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><version>1.0-SNAPSHOT</version><modules><module>auth</module><module>order</module></modules><packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

创建auth认证授权服务

依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>spring-cloud-starter-oauth2</artifactId><groupId>org.cyj</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>auth</artifactId><dependencies><!--spring boot 相关--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--spring cloud oauth2 相关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><exclusions><exclusion><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId></exclusion></exclusions></dependency><!--springboot 2.1.3 版本 可能不兼容 spring-security-oauth2-autoconfigure:2.1.0.M4 低版本吧所以我在上边排除spring-security-oauth2-autoconfigure 依赖--><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.1.3.RELEASE</version></dependency><!--其他 依赖--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

工程结构如下:

SQL脚本:

/*
SQLyog Enterprise v12.09 (64 bit)
MySQL - 5.7.31 : Database - spring-security
*********************************************************************
*/
/*!40101 SET NAMES utf8 */ ;/*!40101 SET SQL_MODE=''*/ ;/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */ ;/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */ ;/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */ ;/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */ ;CREATE DATABASE /*!32312 IF NOT EXISTS*/ `spring-security` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ ;USE `spring-security` ;/*Table structure for table `t_user` */
DROP TABLE IF EXISTS `t_user` ;CREATE TABLE `t_user` (`id` BIGINT (20) NOT NULL COMMENT '用户id',`username` VARCHAR (64) NOT NULL COMMENT '用户登录账号',`password` VARCHAR (64) NOT NULL COMMENT '用户登录密码',`fullname` VARCHAR (255) NOT NULL COMMENT '用户姓名',`mobile` VARCHAR (11) DEFAULT NULL COMMENT '手机号',PRIMARY KEY (`id`) USING BTREE
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '用户表' ;/*Data for the table `t_user` */
INSERT INTO `t_user` (`id`,`username`,`password`,`fullname`,`mobile`
)
VALUES(1,'zhangsan','$2a$10$o/FkX0ss2mr6ligiO6AP9.z8ecTiBhJpqjew.iEGq4.s.V8r1UKRa','张三','16680804545'),(2,'lisi','$2a$10$InoDpP3VaYFNEPBbNrE3fOiEWFYgvIVLkuG/BzKF8jiPLjItGGFN6','李四','16680804545') ;/*!40101 SET SQL_MODE=@OLD_SQL_MODE */ ;/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */ ;/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */ ;/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */ ;

代码编写

配置文件
在resources下创建application.properties

spring.application.name=auth
server.port=8080
server.servlet.context-path=/auth
# 数据源配置
spring.datasource.url=jdbc:mysql://192.168.88.128:3306/spring-security?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

启动类

package com.cyj.security.oauth2.auth;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-29 22:08**/
@SpringBootApplication
public class AuthApplication {public static void main(String[] args) {SpringApplication.run(AuthApplication.class, args);}
}

entity

package com.cyj.security.oauth2.auth.entity;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-29 11:05**/
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {private Long id;private String username;private String password;private String fullname;private String mobile;
}
package com.cyj.security.oauth2.auth.entity;import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;import java.util.Collection;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-29 11:30**/
@Getter
public class MyUserDetails extends User {/*** 这里我只用简单的 用户名 密码  权限集合* 还有一个复杂的方法** @param username* @param password* @param authorities*/public MyUserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {super(username, password, authorities);}
}

mapper,service

package com.cyj.security.oauth2.auth.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cyj.security.oauth2.auth.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-29 11:18**/
@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {}
package com.cyj.security.oauth2.auth.service;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cyj.security.oauth2.auth.entity.MyUserDetails;
import com.cyj.security.oauth2.auth.entity.User;
import com.cyj.security.oauth2.auth.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;import java.util.List;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-30 13:29**/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {@Autowiredprivate UserMapper userMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userMapper.selectOne(new QueryWrapper<User>().eq("username", username));if (StringUtils.isEmpty(user)) {throw new UsernameNotFoundException("用户不存在");}//我这里弄一个简单的权限集合,真实的开发中是要查询数据库的List<GrantedAuthority> atuh = AuthorityUtils.commaSeparatedStringToAuthorityList("admin,p1");//从数据库查出的用户信息赋值给security框架中user对象return new MyUserDetails(user.getUsername(),user.getPassword(),atuh);}
}

controller

package com.cyj.security.oauth2.auth.controller;import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-28 20:41**/
@RestController
public class LoginController {@RequestMapping(value = "/login-success", produces = {"text/plain;charset=utf-8"})public String loginSuccess() {String username = getUsername();return username + " 登录成功";}/*** 获取当前登录用户名** @return*/private String getUsername() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();if (!authentication.isAuthenticated()) {return null;}Object principal = authentication.getPrincipal();String username = null;if (principal instanceof org.springframework.security.core.userdetails.UserDetails) {username =((org.springframework.security.core.userdetails.UserDetails) principal).getUsername();} else {username = principal.toString();}return username;}}

WebSecurityConfig

package com.cyj.security.oauth2.auth.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** @Program: Spring-Security-OAuth2* @Description:* @Author C_Y_J* @Create: 2021-01-30 00:21**/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {/*** 密码编码器** @return*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 安全拦截机制(最重要)** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable();http.authorizeRequests().antMatchers("/r/r1").hasAnyAuthority("p1").anyRequest().authenticated();http//允许表单登录.formLogin()//自定义登录成功的页面地址.successForwardUrl("/login-success");}
}

访问 http://localhost:8080/auth/login 输入正确的用户名和密码,登录成功

前言

到此为止还是没用上oauth2.0的知识点,只是简单的做了一个登录接口,接下来跟着我的思路来:把刚才的写的auth服务当作成微信认证授权服务,张三是微信用户,现在有一个平台A想通过auth服务(微信认证授权服务)拿到张三的个人信息。接着往下看!

认证授权服务器配置

AuthorizationServerConfigurerAdapter

AuthorizationServerConfigurerAdapter要求配置以下几个类,这几个类是由Spring创建的独立的配置对象,它们会被Spring传入AuthorizationServerConfigurer中进行配置。

public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {public AuthorizationServerConfigurerAdapter() {}public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {}public void configure(ClientDetailsServiceConfigurer clients) throws Exception {}public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {}
}

上面这个AuthorizationServerConfigurerAdapter是人家框架写好的,我们重写它的方法,一步一步跟着我走,我会逐一解释

授权码模式

====================================================================

ClientDetailsServiceConfigurer 用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。ClientDetails有几个重要的属性如下列表:

clientId:(必须的)用来标识客户的Id。
secret:(需要值得信任的客户端)客户端安全码,如果有的话。
scope:用来限制客户端的访问范围,如果为空(默认)的话,那么客户端拥有全部的访问范围。
authorizedGrantTypes:此客户端可以使用的授权类型,默认为空。
authorities:此客户端可以使用的权限(基于Spring Security authorities)。

客户端详情(Client Details)能够在应用程序运行的时候进行更新,可以通过访问底层的存储服务(例如将客户端详情存储在一个关系数据库的表中,就可以使用 JdbcClientDetailsService)或者通过自己实现ClientRegistrationService接口(同时你也可以实现 ClientDetailsService 接口)来进行管理。

我们暂时使用内存方式存储客户端详情信息,配置如下:

package com.cyj.security.oauth2.auth.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;/*** @Program: Spring-Security-OAuth2* @Description: 配置OAuth2.0认证授权服务器* @Author C_Y_J* @Create: 2021-01-29 22:34**/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {/*** 客户端详情** @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients// 使用in‐memory存储.inMemory()// client_id.withClient("c1")//客户端密钥.secret(new BCryptPasswordEncoder().encode("secret"))//客户端访问的资源列表.resourceIds("res1")// 该client允许的授权类型 authorization_code,password,refresh_token,implicit,client_credentials.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")// 允许的授权范围.scopes("all")//false 允许跳转到授权页面.autoApprove(false)//加上验证回调地址.redirectUris("http://www.baidu.com");}
}

重启项目,登录 http://localhost:8080/auth/login

紧接着我们访问 http://localhost:8080/auth/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com

分析:在代码里面的 c1 我们把它当成平台A,平台A想拿到微信用户张三的个人信息。
首先,我们的平台A要主动去访问auth认证授权服务(微信认证授权服务)的授权端点。输入平台A的信息:
client_id:c1
response_type:code
scope:all
redirect_uri:http://www.baidu.com

平台A输入的信息会和 auth认证授权服务(微信认证授权服务)存储的信息做对比,如果一致,代表平台A是一个合法的平台。

这个时候 auth认证授权服务(微信认证授权服务)就会提醒张三用户,你是同意还是拒绝平台A访问你的一个信息呢?也就是下面的这幅图。


这个时候你点击Approve 再点击Authorize

注意观察浏览器的地址栏的变化

http://localhost:8080/auth/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com

https://www.baidu.com/?code=lQyBvO


看到了一个授权码,但是拿到授权码感觉没用,平台A想要的是张三用户的个人信息,所以接下来,ouath2.0的协议思路是这样的。

1、平台A获取到授权码,请求 auth认证授权服务(微信认证授权服务)申请令牌 此过程用户看不到,平台A请求 auth认证授权服务(微信认证授权服务),请求携带授权码。

2、 auth认证授权服务(微信认证授权服务)验证平台A请求的授权码,如果合法则给平台A颁发令牌,令牌是平台A拿到张三用户个人信息的通行证。

====================================================================

AuthorizationServerEndpointsConfigurer 用来配置令牌(token)的访问端点和令牌服务(token services)。

AuthorizationServerEndpointsConfigurer 通过设定以下属性决定支持的授权类型(Grant Types):

authenticationManager:认证管理器,当你选择了资源所有者密码(password)授权类型的时候,请设置这个属性注入一个AuthenticationManager 对象。

userDetailsService:如果你设置了这个属性的话,那说明你有一个自己的 UserDetailsService
接口的实现,或者你可以把这个东西设置到全局域上面去(例如 GlobalAuthenticationManagerConfigurer
这个配置对象),当你设置了这个之后,那么 “refresh_token” 即刷新令牌授权类型模式的流程中就会包含一个检查,用来确保这个账号是否仍然有效,假如说你禁用了这个账户的话。

authorizationCodeServices:这个属性是用来设置授权码服务的(即 AuthorizationCodeServices
的实例对象),主要用于 “authorization_code” 授权码类型模式。

implicitGrantService:这个属性用于设置隐式授权模式,用来管理隐式授权模式的状态。

tokenGranter:当你设置了这个东西(即 TokenGranter 接口实现),那么授权将会交由你来完全掌控,并且会忽略掉上面的这几个属性,这个属性一般是用作拓展用途的,即标准的四种授权模式已经满足不了你的需求的时候,才会考虑使用这个。

AuthorizationServerEndpointsConfigurer 这个配置对象有一个叫做 pathMapping() 的方法用来配置端点URL链接,它有两个参数:

第一个参数:String 类型的,这个端点URL的默认链接。
第二个参数:String 类型的,你要进行替代的URL链接

以上的参数都将以 “/” 字符为开始的字符串,框架的默认URL链接如下列表,可以作为这个 pathMapping() 方法的第一个参数:

/oauth/authorize:授权端点。
/oauth/token:令牌端点。
/oauth/confirm_access:用户确认授权提交端点。
/oauth/error:授权服务错误信息端点。
/oauth/check_token:用于资源服务访问的令牌解析端点。
/oauth/token_key:提供公有密匙的端点,如果你使用JWT令牌的话。

在 AuthorizationServer 类中 添加代码

      /** ==============================================================================*//*** 令牌存储策略*/@Autowiredprivate TokenStore tokenStore;/*** 客户端详情服务*/@Autowiredprivate ClientDetailsService clientDetailsService;/*** 令牌存储策略** @return*/@Beanpublic TokenStore tokenStore() {//使用内存存储(普通令牌)return new InMemoryTokenStore();}/*** 令牌管理服务** @return*/@Beanpublic AuthorizationServerTokenServices tokenService() {DefaultTokenServices service = new DefaultTokenServices();//客户端详情服务service.setClientDetailsService(clientDetailsService);//支持刷新令牌service.setSupportRefreshToken(true);//令牌存储策略service.setTokenStore(tokenStore);// 令牌默认有效期2小时service.setAccessTokenValiditySeconds(7200);// 刷新令牌默认有效期3天service.setRefreshTokenValiditySeconds(259200);return service;}/** ==============================================================================*//*** 认证管理器*/@Autowiredprivate AuthenticationManager authenticationManager;/*** 授权码模式服务*/@Autowiredprivate AuthorizationCodeServices authorizationCodeServices;@Beanpublic AuthorizationCodeServices authorizationCodeServices() {//设置授权码模式的授权码如何存取,暂时采用内存方式return new InMemoryAuthorizationCodeServices();}/*** 令牌访问端点配置** @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints//认证管理器.authenticationManager(authenticationManager)//授权码服务.authorizationCodeServices(authorizationCodeServices)//令牌管理服务.tokenServices(tokenService()).allowedTokenEndpointRequestMethods(HttpMethod.POST);}

====================================================================

AuthorizationServerSecurityConfigurer 用来配置令牌端点的安全约束。

在 AuthorizationServer 类中 添加代码

    /** ==============================================================================*//*** 令牌端点的安全约束** @param security*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) {security//oauth/token_key是公开(提供公有密匙的端点,如果你使用JWT令牌的话).tokenKeyAccess("permitAll()")//oauth/check_token公开(用于资源服务访问的令牌解析端点).checkTokenAccess("permitAll()")//表单认证(申请令牌).allowFormAuthenticationForClients();}

补充:在 WebSecurityConfig 添加认证管理器

    /*** 认证管理器** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}

重启项目
登录 http://localhost:8080/auth/login

紧接着我们访问 http://localhost:8080/auth/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com

拿到code值:

https://www.baidu.com/?code=rdP7m1

因为申请令牌是post接口,所以用Postman来测试

http://localhost:8080/auth/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=rdP7m1&redirect_uri=http://www.baidu.com

参数列表如下:
client_id:客户端唯一标识。
client_secret:客户端秘钥。
grant_type:授权类型,填写authorization_code,表示授权码模式
code:授权码,就是刚刚获取的授权码,注意:授权码只使用一次就无效了,需要重新申请。
redirect_uri:申请授权码时的跳转url,一定和申请授权码时用的redirect_uri一致。


认证授权服务器返回令牌(access_token)

{"access_token": "e25b319a-c1b9-4f27-89e8-e2f93f7415ea","token_type": "bearer","refresh_token": "40d80a03-d293-4d14-a35c-85df669c9849","expires_in": 43199,"scope": "all"
}

刚才这种模式是四种模式中最安全的一种模式,也叫授权码模式。一般用于client是Web服务器端应用或第三方的原生App调用资源服务的时候。因为在这种模式中access_token不会经过浏览器或移动端的App,而是直接从服务端去交换,这样就最大限度的减小了令牌泄漏的风险。

====================================================================
简化模式客户端模式
在这里不做介绍,这两种不常见

密码模式
(1)张三将用户名、密码发送给平台A
(2)平台A拿着张三的用户名、密码向 auth认证授权服务(微信认证授权服务)请求令牌(access_token)

还是上面的代码,我们接着来访问:
http://localhost:8080/auth/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=zhangsan&password=123

参数列表如下:
client_id:客户端唯一标识。
client_secret:客户端秘钥。
grant_type:授权类型,填写password表示密码模式
username:资源拥有者用户名。
password:资源拥有者密码。

原文链接

(七)Spring Security (spring-cloud-starter-oauth2)应用详解------认证授权服务------授权码模式和密码模式相关推荐

  1. spring security(三)oauth2

    oauth2.0: 阮一峰理解OAuth 2.0:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html https://www.kancloud. ...

  2. Spring Security 实战干货:OAuth2登录获取Token的核心逻辑

    作者 | 码农小胖哥 来源 | https://mp.weixin.qq.com/s/zdTBdSVunqwVGx-spHjLjw 1. 前言 在上一篇Spring Security 实战干货:OAu ...

  3. Spring Security 实战干货:OAuth2授权回调的核心认证流程

    1. 前言 我们在上一篇 Spring Security 实战干货:OAuth2 授权回调的处理机制 对 OAuth2 服务端调用客户端回调的流程进行了图解, 今天我们来深入了解 OAuth2 在回调 ...

  4. Spring Security 实战干货:OAuth2第三方授权初体验

    1. 前言 现在很多项目都有第三方登录或者第三方授权的需求,而最成熟的方案就是OAuth2.0授权协议.Spring Security也整合了OAuth2.0,在目前最新的 Spring Securi ...

  5. Spring Security+Spring Data Jpa 强强联手,安全管理只有更简单!

    Spring Security+Spring Data Jpa 强强联手,安全管理没有简单,只有更简单! 这周忙着更新 OAuth2,Spring Security 也抽空来一篇. Spring Se ...

  6. Spring Security + Spring Session Redis——【SecurityContext】和【AuthenticationToken】JSON反序列化问题解决方案

    前置 Spring Session + Redis--自定义JSON序列化解决方案 问题描述 Spring Security + Spring Session使用中Redis,默认序列化方式是JdkS ...

  7. 【夯实Spring Cloud】Spring Cloud分布式配置中心详解

    本文属于[夯实Spring Cloud]系列文章,该系列旨在用通俗易懂的语言,带大家了解和学习Spring Cloud技术,希望能给读者带来一些干货.系列目录如下: [夯实Spring Cloud]D ...

  8. Spring Boot 使用 HikariCP 连接池配置详解

    Spring Boot 使用 HikariCP 连接池配置详解 HikariCP 是一个高性能的 JDBC 连接池组件. Spring Boot 2.x 将其作为默认的连接池组件,项目中添加 spri ...

  9. Spring三级缓存解决循环依赖问题详解

    spring三级缓存解决循环依赖问题详解 前言 这段时间阅读了spring IOC部分的源码.在学习过程中,自己有遇到过很多很问题,在上网查阅资料的时候,发现很难找到一份比较全面的解答.现在自己刚学习 ...

最新文章

  1. Linux 文件系统剖析
  2. 深入浅出统计学(十三)假设检验
  3. 云告警平台 OneAlert :如何帮助运维工程师做好汇报?
  4. github创建项目,并提交本地文件
  5. 11g crsctl start/stop crs 和 crsctl start/stop cluster 的关系
  6. 以太坊源码分析——BlockChain
  7. URL重写 对于禁用cookie的 方法
  8. kafka的push与poll
  9. OC语言-04-OC语言-核心语法
  10. UNIX网络编程 第1卷 数据分享
  11. 【C语言】VSCode配置C语言开发环境(详细图文)
  12. 程序员微信名昵称_微信名字大全
  13. 技术狂潮下的生理性健忘:科技产品如何影响我们的大脑?
  14. UG NX 12 草图设计
  15. SQL数据修复,SQL数据库修复,SQL数据库修复软件,SQL数据库恢复,SQL数据库日志恢复软件
  16. Python将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
  17. Unity跟随鼠标顺时针或逆时针旋转之美
  18. 观点 | 银行业数据应用的瓶颈与打开思路
  19. 【分布式计算】什么是分布式系统
  20. docker容器IP的设置

热门文章

  1. 用Github Pages+Hexo搭建博客之(八)Hexo博客Next主题添加统计文章阅读量(访问量/浏览量/阅读次数)功能
  2. React 中ref 的使用(类组件和函数组件)以及forwardRef 与 useImperativeHandle 详解
  3. 点线面的意义_1.点线面三元素在平面构成中的造型意义是什么?
  4. windows64位系统完全卸载winpcap的方式
  5. DNF台版云服务器搭建(非商用,可联机)
  6. 宏文件下载_SolidWorks模型英文特征改中文名字方法分享SolidWorks宏文件 [
  7. Java-Eddy的难题
  8. hype3 响应布局_使用Hype 3的基于时间轴的Web动画
  9. 不属于python特点的是_Python程序设计课后习题答案-第一单元
  10. 透过达达财报看同城零售赛道价值,平台规模化增长后撑起更大价值