Spring Boot Security Oauth2之客户端模式及密码模式实现

示例主要内容

  • 1.多认证模式(密码模式、客户端模式)
  • 2.token存到redis支持
  • 3.资源保护
  • 4.密码模式用户及权限存到数据库
  • 5.使用说明

示例代码-github

介绍

oauth2 client credentials 客户端模式获取access_token流程

客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

  • (A)客户端向认证服务器进行身份认证,并要求一个访问令牌。客户端发出的HTTP请求,包含以下参数:

    granttype:表示授权类型,此处的值固定为"clientcredentials",必选项。

    scope:表示权限范围,可选项。

  • (B)认证服务器确认无误后,向客户端提供访问令牌。

oauth2 password 密码模式获取access_token流程

密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。

在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

  • (A)用户向客户端提供用户名和密码。

  • (B)客户端将用户名和密码发给认证服务器,向后者请求令牌。 客户端发出的HTTP请求,包含以下参数:

    grant_type:表示授权类型,此处的值固定为"password",必选项。

    username:表示用户名,必选项。

    password:表示用户的密码,必选项。

    scope:表示权限范围,可选项。

  • (C)认证服务器确认无误后,向客户端提供访问令牌。

Oauth2提供的默认端点(endpoints)

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

示例使用介绍

1.端模式获取access_token

http://localhost:8080/oauth/token?grant_type=client_credentials&scope=select&client_id=client_1&client_secret=123456

返回结果

{
"access_token": "67a2c8f6-bd08-4409-a0d6-6ba61a4be950",
"token_type": "bearer",
"expires_in": 41203,
"scope": "select"
}

2.密码模式获取access_token

http://localhost:8080/oauth/token?username=user&password=123456&grant_type=password&scope=select&client_id=client_2&client_secret=123456

返回结果

{
"access_token": "b3d2c131-1225-45b4-9ff5-51ec17511cee",
"token_type": "bearer",
"refresh_token": "8495d597-0560-4598-95ef-143c0855363c",
"expires_in": 42417,
"scope": "select"
}

3.刷新access_token

http://localhost:8080/oauth/token?grant_type=refresh_token&refresh_token=8495d597-0560-4598-95ef-143c0855363c&client_id=client_2&client_secret=123456

返回结果

{
"access_token": "63de6c71-672f-418c-80eb-0c9abc95b67c",
"token_type": "bearer",
"refresh_token": "8495d597-0560-4598-95ef-143c0855363c",
"expires_in": 43199,
"scope": "select"
}

4.访问受保护的资源

http://localhost:8080/order/1?access_token=b3d2c131-1225-45b4-9ff5-51ec17511cee

正确返回数据

spring security oauth2代码过程

security oauth2 整合的3个核心配置类

  • 1.资源服务配置 ResourceServerConfiguration
  • 2.授权认证服务配置 AuthorizationServerConfiguration
  • 3.security 配置 SecurityConfiguration

1.pom.xml添加maven依赖

    <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> <dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.6.RELEASE</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
</dependency> <dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency> <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>

主要使用了:security、oauth2、redis、mysql、mybatis-plus等组件

2.认证授权配置AuthorizationServerConfigurerAdapter.java

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { private static final String RESOURCE_IDS = "order"; @Autowired
AuthenticationManager authenticationManager; @Autowired
RedisConnectionFactory redisConnectionFactory; @Autowired
private UserDetailsService userDetailsService; @Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception { String finalSecret = "{bcrypt}" + new BCryptPasswordEncoder().encode("123456");
//配置两个客户端,一个用于password认证一个用于client认证
clients.inMemory() //client模式
.withClient("client_1")
.resourceIds(RESOURCE_IDS)
.authorizedGrantTypes("client_credentials", "refresh_token")
.scopes("select")
.authorities("oauth2")
.secret(finalSecret) .and() //密码模式
.withClient("client_2")
.resourceIds(RESOURCE_IDS)
.authorizedGrantTypes("password", "refresh_token")
.scopes("select")
.authorities("oauth2")
.secret(finalSecret);
} /**
* 认证服务端点配置
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
//用户管理
.userDetailsService(userDetailsService)
//token存到redis
.tokenStore(new RedisTokenStore(redisConnectionFactory))
//启用oauth2管理
.authenticationManager(authenticationManager)
//接收GET和POST
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
} @Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer.allowFormAuthenticationForClients();
}
}

3.资源配置ResourceServerConfig.java

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter { private static final String RESOURCE_IDS = "order"; @Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_IDS).stateless(true);
} @Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/order/**").authenticated(); //配置order访问控制,必须认证过后才可以访问 }
}

4.密码模式的用户及权限存到了数据库,UserDetailsServiceImpl.java


@Service
public class UserDetailsServiceImpl implements UserDetailsService { @Autowired
private UserServiceImpl userService; /**
* 实现UserDetailsService中的loadUserByUsername方法,用于加载用户数据
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userService.queryUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
} //用户权限列表
Collection<? extends GrantedAuthority> authorities = userService.queryUserAuthorities(user.getId()); return new AuthUser(
user.getId(),
user.getUsername(),
user.getPassword(),
true,
true,
true,
true,
authorities);
}
}

5.WebSecurityConfig配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
} /**
* 注入AuthenticationManager接口,启用OAuth2密码模式
*
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
} /**
* 通过HttpSecurity实现Security的自定义过滤配置
*
* @param httpSecurity
* @throws Exception
*/
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.requestMatchers().anyRequest()
.and()
.authorizeRequests()
.antMatchers("/oauth/**").permitAll();
}
}

6.application.yml配置

server:
port: 8080 spring:
thymeleaf:
encoding: UTF-8
cache: false datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/easy_web?useSSL=false&serverTimezone=UTC
username: root
password: 123456 redis:
host: 127.0.0.1
port: 6379
password: logging.level.org.springframework.security: DEBUG

7.inital.sql数据库初始化脚本

DROP TABLE IF EXISTS `user`;
DROP TABLE IF EXISTS `role`;
DROP TABLE IF EXISTS `user_role`;
DROP TABLE IF EXISTS `role_permission`;
DROP TABLE IF EXISTS `permission`; CREATE TABLE `user` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `user_role` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(11) NOT NULL,
`role_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `role_permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`role_id` bigint(11) NOT NULL,
`permission_id` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `permission` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) NOT NULL,
`name` varchar(255) NOT NULL,
`description` varchar(255) NULL,
`pid` bigint(11) NOT NULL,
PRIMARY KEY (`id`)
); INSERT INTO user (id, username, password) VALUES (1,'user','{bcrypt}$2a$10$Tme77eHtXzcB8ghQUepYguJr7P7ESg0Y7XHMnk60s.kf2A.BWBD9m');
INSERT INTO user (id, username , password) VALUES (2,'admin','{bcrypt}$2a$10$Tme77eHtXzcB8ghQUepYguJr7P7ESg0Y7XHMnk60s.kf2A.BWBD9m');
INSERT INTO role (id, name) VALUES (1,'USER');
INSERT INTO role (id, name) VALUES (2,'ADMIN');
INSERT INTO permission (id, url, name, pid) VALUES (1,'/user/common','common',0);
INSERT INTO permission (id, url, name, pid) VALUES (2,'/user/admin','admin',0);
INSERT INTO user_role (user_id, role_id) VALUES (1, 1);
INSERT INTO user_role (user_id, role_id) VALUES (2, 1);
INSERT INTO user_role (user_id, role_id) VALUES (2, 2);
INSERT INTO role_permission (role_id, permission_id) VALUES (1, 1);
INSERT INTO role_permission (role_id, permission_id) VALUES (2, 1);
INSERT INTO role_permission (role_id, permission_id) VALUES (2, 2);

经过以上七个步骤,我们快速实现了Oauth2的密码模式和客户模式功能。

资料

Spring Boot Security Oauth2之客户端模式及密码模式实现的更多相关文章

  1. Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器

    概要 之前的两篇文章,讲述了Spring Security 结合 OAuth2 .JWT 的使用,这一节要求对 OAuth2.JWT 有了解,若不清楚,先移步到下面两篇提前了解下. Spring Bo ...

  2. Spring Boot Security 整合 OAuth2 设计安全API接口服务

    简介 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用,目前的版本是2.0版.本文重点讲解Spring Boot项目对OAuth2进行的实现,如果你对OAut ...

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

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

  4. Spring Boot Security配置教程

    1.简介 在本文中,我们将了解Spring Boot对spring Security的支持. 简而言之,我们将专注于默认Security配置以及如何在需要时禁用或自定义它. 2.默认Security设 ...

  5. Spring Boot Security 整合 JWT 实现 无状态的分布式API接口

    简介 JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案.JSON Web Token 入门教程 - 阮一峰,这篇文章可以帮你了解JWT的概念.本文重点讲解Spring Boo ...

  6. Spring Boot Security JWT 整合实现前后端分离认证示例

    前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...

  7. Spring Boot 与 OAuth2 官方最详细教程

    https://mp.weixin.qq.com/s?__biz=MzU0MDEwMjgwNA==&mid=2247484357&idx=1&sn=73e501de8591e6 ...

  8. boke练习: spring boot: security post数据时,要么关闭crst,要么添加隐藏域

    spring boot: security post数据时,要么关闭crst,要么添加隐藏域 http.csrf().disable(); 或者: <input name="${_cs ...

  9. 使用Spring Cloud Security OAuth2搭建授权服务

    阅读数:84139 前言: 本文意在抛砖引玉,帮大家将基本的环境搭起来,具体实战方案还要根据自己的业务需求进行制定.我们最终没有使用Spring Security OAuth2来搭建授权服务,而是完全 ...

随机推荐

  1. 基于lua-nginx-module(openresty)的WEB应用防火墙

    独乐乐,不如众乐乐,分享给大家一篇WEB应用防火墙的文章,基于Lua+ Nginx实现.以下是ngx_lua_waf的作者全文输出. Github地址:https://github.com/loves ...

  2. kuangbin专题专题四 Heavy Transportation POJ - 1797

    题目链接:https://vjudge.net/problem/POJ-1797 思路:请参考我列出的另一个题目,和这个题目要求的值相反,另一个清楚后,这个写的解释就明白了. 另一个类似题目的博客:h ...

  3. Socket编程(C语言实现):bind()函数英文翻译

    本篇翻译的bind()函数,我参考的国外网站是: bind 朋友们可以自由转载我对英文的中文翻译,但是对于"作者注:"的描述,转载时请注明出处和作者,否则视为侵权. 下面是翻译的正 ...

  4. 如何在vue中监听scroll,从而实现滑动加载更多

    首先需要明确3个定义: 文档高度:整个页面的高度 可视窗口高度:你看到的浏览器可视屏幕高度 滚动条滚动高度: 滚动条下滑过的高度 当 文档高度 = 可视窗口高度 + 滚动条高度  时,滚动条正好到底. ...

  5. MyBatis从入门到精通:insert用法

    2.4.1 简单的insert方法 1.接口类中的方法: int insert(SysUser sysUser); 2.映射文件中的修改: <!-- insert标签包含如下的属性: id: p ...

  6. 性能测试-实例讲解VU、RPS、RT公式换算

    概述 今天看到一篇文章讲解VU.RPS.RT,中间有一个公式如下图 并发数 = RPS * 响应时间  于是我在本地做了几次实验,试图验证一下公式的准确性 实验网站 www.baidu.com 第一次 ...

  7. VSCode 云同步扩展设置 Settings Sync 插件

    VSCode 云同步扩展设置 Settings Sync 插件 Hi.大家好,今天又是美好的一天. 关于 Settings Sync扩展: Settings Sync可以同步你当前的VSCode配置环 ...

  8. Spring+SpringMVC+mybatis maven pom文件

    pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w ...

  9. Docker部署web环境之Lanmp

    1. 案例一 整套项目多容器分离通过docker-compose部署lanmp环境 中方文档参考网址: docker/kubernets网址 http://www.dockerinfo.net/doc ...

  10. python List交集、并集、差集

    工作中遇到了求两个集合的差集,但是集合集合中包含字典,所以使用difference方法会报错,看了一些别人的博客,整理了一下. 1. 获取两个list 的交集print list(set(a).int ...