核心 POM

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId><version>2.2.6.RELEASE</version>
</dependency>

配置 WebSecurityConfig 开启 Spring 方法级的安全保护

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.config.http.SessionCreationPolicy;/*** 开启Spring方法级的安全保护*/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {/*** 授权码模式在浏览器地址栏发起请求来获取 code* .anyRequest().authenticated() 必须对该请求进行认证拦截,发现用户没有登陆的时候会弹出登陆框, 从而让用户输入用户名和密码进行登陆, 若是对该请求进行放行, 则登陆页无法弹出, 并抛出 InsufficientAuthenticationException* .httpBasic() 因为用户未登陆访问了受保护的资源, 所以还要开启 httpBasic 进行简单认证, 否则会抛出 AccessDeniedException 异常,*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable()//关闭跨域保护.authorizeRequests().antMatchers("/captcha/**").permitAll().anyRequest().authenticated().and().httpBasic().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)//永远不会创建HttpSession, 默认配置.and().headers().cacheControl().disable()//禁用缓存;}/*** 注入一个认证管理器, 自身不实现身份验证, 而是逐一向认证提供者进行认证, 直到某一个认证提供者能够成功验证当前用户的身份* * AuthenticationManager(认证管理器接口) 的默认实现类 ProviderManager, 管理多个 AuthenticationProvider(认证提供者)*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}}

配置 TokenConfig 来定义 Token 的生成方式

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;/*** 配置token*/
@Configuration
public class TokenConfig {@Beanpublic TokenStore jwtTokenStore() {//令牌存储方案采用JWTreturn new JwtTokenStore(jwtAccessTokenConverter());}/** AccessToken转换器: 定义 token 的生成方式* JwtAccessTokenConverter: 表示采用 JWT 来生成*/@Beanpublic JwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey(OauthConstant.OAUTH_SIGNING_KEY); //对称秘钥,资源服务器使用该秘钥来验证return converter;}}

配置 UserDetailsService 和 JdbcClientDetailsService 获取用户和客户端信息

自定义客户端表结构

-- oauth2.0 默认有一套客户端表结构可进行替换,以下为自定义,其他用户的表结构就自行定义吧
CREATE TABLE `sys_client` (`id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',`client_id` varchar(32) NOT NULL COMMENT '客户端ID',`resource_ids` varchar(256) DEFAULT NULL COMMENT '客户端密钥',`client_secret` varchar(256) DEFAULT NULL COMMENT '资源ID列表',`scope` varchar(256) DEFAULT NULL COMMENT '作用域',`authorized_grant_types` varchar(256) DEFAULT NULL COMMENT '授权方式',`web_server_redirect_uri` varchar(256) DEFAULT NULL COMMENT '回调地址',`authorities` varchar(256) DEFAULT NULL COMMENT '权限列表',`access_token_validity` int DEFAULT NULL COMMENT '令牌有效时间',`refresh_token_validity` int DEFAULT NULL COMMENT '刷新令牌有效时间',`additional_information` varchar(4096) DEFAULT NULL COMMENT '扩展信息',`autoapprove` varchar(256) DEFAULT NULL COMMENT '是否自动放行',`deleted` char(1) DEFAULT '0' COMMENT '删除标记,1:已删除,0:正常',`platform_id` int NOT NULL DEFAULT '0' COMMENT '所属平台',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='客户端信息表';-- 插入两条测试客户端
INSERT INTO `platform`.`sys_client`(`id`, `client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `deleted`, `platform_id`) VALUES (1, 'c1', '', '$2a$10$1Bg3qCxNVXobR2SJG9t0zOV45glOCH1MpvvPJDdyXCycWu/rZ1DOa', 'all', 'refresh_token,authorization_code,client_credentials,implicit', 'http://www.baidu.com', NULL, 72000, 259200, NULL, 'false', '0', 0);
INSERT INTO `platform`.`sys_client`(`id`, `client_id`, `resource_ids`, `client_secret`, `scope`, `authorized_grant_types`, `web_server_redirect_uri`, `authorities`, `access_token_validity`, `refresh_token_validity`, `additional_information`, `autoapprove`, `deleted`, `platform_id`) VALUES (2, 'c2', 'mo-wen-res', '$2a$10$1Bg3qCxNVXobR2SJG9t0zOV45glOCH1MpvvPJDdyXCycWu/rZ1DOa', 'all', 'password,refresh_token,captcha,authorization_code', 'http://www.baidu.com', NULL, 72000, 259200, NULL, 'false', '0', 0);
-- 查询客户端信息
String OAUTH_SQL_CLIENT = "SELECT client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove\n" +"FROM sys_client WHERE client_id = ? AND deleted = 0";-- 查询用户信息
String OAUTH_SQL_LOGIN_USER = "select user_id as id, `name`, phone, password from sys_user where phone = ?";-- 查询用户权限
String OAUTH_SQL_USER_PERMISSION = "SELECT `name` FROM sys_permission WHERE id IN(\n" +"      SELECT permission_id FROM sys_role_permission WHERE role_id IN(\n" +"          SELECT role_id FROM sys_user_role WHERE user_id = ?\n" +"      )\n" +")";

定义 UserDetailsService 的实现类用于查询用户信息

@Slf4j
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {// 查询用户信息的service, 自行定义private final UserService userService;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {LoginUser loginUser = userService.getUserByPhone(s);List<String> authorities = userService.getPermissionsByUserId(loginUser.getId());log.info("当前登陆用户: [{}] 权限: [{}]", loginUser, authorities);return User.withUsername(toJSONString(loginUser)).password(loginUser.getPassword()).authorities(authorities.toArray(new String[0])).build();}}

重写 JdbcClientDetailsService 用于查询客户端信息

@Slf4j
@Service
public class JdbcClientDetailsServiceImpl extends JdbcClientDetailsService {public JdbcClientDetailsServiceImpl(DataSource dataSource) {super(dataSource);}@Resourceprivate PasswordEncoder bCryptPasswordEncoder;@Overridepublic ClientDetails loadClientByClientId(String clientId) throws InvalidClientException {super.setSelectClientDetailsSql(OauthConstant.OAUTH_SQL_CLIENT);super.setPasswordEncoder(bCryptPasswordEncoder);ClientDetails clientDetails = super.loadClientByClientId(clientId);log.info("加载客户端信息: [{}], [{}]", clientId, clientDetails);return clientDetails;}//用于密码的加密方式@Beanpublic PasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}}

继承 AuthorizationServerConfigurerAdapter 来实现认证服务器的核心配置❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️

@Configuration
@EnableAuthorizationServer
@AllArgsConstructor
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {private final JdbcClientDetailsServiceImpl clientDetailsServiceImpl;private final UserDetailsServiceImpl userDetailsServiceImpl;private final TokenStore jwtTokenStore;private final JwtAccessTokenConverter jwtAccessTokenConverter;private final AuthenticationManager authenticationManager;private final PasswordEncoder bCryptPasswordEncoder;private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;private final CustomWebResponseExceptionTranslator customWebResponseExceptionTranslator;/*** 用来配置令牌端点的安全约束, 密码校验方式等*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients().passwordEncoder(bCryptPasswordEncoder).tokenKeyAccess("permitAll()")                    //oauth/token_key是公开.checkTokenAccess("permitAll()")                  //oauth/check_token公开;}/*** 用来配置客户端详情服务(ClientDetailsService), 客户端详情信息在这里进行初始化*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(clientDetailsServiceImpl);}/*** 用来配置令牌(token)的访问端点和令牌服务* 配置令牌的访问端点:即申请令牌的URL .pathMapping(defaultPath, customPath)* 令牌服务:令牌的生成和发放规则(TokenConfig)*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.userDetailsService(userDetailsServiceImpl).authenticationManager(authenticationManager)//认证管理器,Password模式配置所需.authorizationCodeServices(authorizationCodeServices())//授权码模式code存储方式定义.tokenStore(jwtTokenStore)//采用jwt方式管理token.accessTokenConverter(jwtAccessTokenConverter)//jwt增强,定义自己的SigningKey.allowedTokenEndpointRequestMethods(HttpMethod.POST, HttpMethod.GET).reuseRefreshTokens(false)//表示重复使用刷新令牌。也就是说会一直重复使用第一次请求到的 refresh_token, 所以要禁止掉;}@Beanpublic AuthorizationCodeServices authorizationCodeServices() { //设置授权码模式的授权码如何存取,暂采用内存方式return new InMemoryAuthorizationCodeServices();}}

测试端口

  • 获取 code:Get /oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
  • 简化模式获取 token:Get /oauth/authorize?response_type=token&client_id=c1&redirect_uri=http://www.baidu.com
  • 密码模式获取 token:Post /oauth/token
    • grant_type:password
    • username:用户名
    • password:密码
    • Authorization:Basic YzI6NDU2 — 请求头添加客户端信息
  • 授权码模式获取 token:Post /oauth/token
    • grant_type:authorization_code
    • code:获取到的 code
    • redirect_uri:重定向url
    • Authorization:Basic YzI6NDU2 — 请求头添加客户端信息
  • 刷新 token:Post /oauth/token
    • grant_type:refresh_token
    • refresh_token:拿到获取token时得到的refresh_token
    • Authorization:Basic YzI6NDU2 — 请求头添加客户端信息

Oauth2.0 系列文章

以下是同步到语雀的、可读性好一点,CSDN 继续看的点专栏就好。
Oauth2.0 核心篇
Oauth2.0 安全性(以微信授权登陆为例)
Oauth2.0 认证服务器搭建
Oauth2.0 添加验证码登陆方式
Oauth2.0 资源服务器搭建
Oauth2.0 自定义响应值以及异常处理
Oauth2.0 补充

Oauth2.0 认证服务器搭建相关推荐

  1. Spring Security OAuth2.0认证授权知识概括

    Spring Security OAuth2.0认证授权知识概括 安全框架基本概念 基于Session的认证方式 Spring Security简介 SpringSecurity详解 分布式系统认证方 ...

  2. Spring Security OAuth2.0认证授权

    文章目录 1.基本概念 1.1.什么是认证 1.2 什么是会话 1.3什么是授权 1.4授权的数据模型 1.4 RBAC 1.4.1 基于角色的访问控制 2.基于Session的认证方式 3.整合案例 ...

  3. SpringSecurity OAuth2.0认证授权-part2

    此篇文章包含oauth2项目搭建.整合jwt.授权方式测试: 篇幅过长,拆分为: part1: 认证授权原理回顾及分布式系统认证方案: part2: oauth2项目搭建.授权方式测试: part3: ...

  4. Spring Security OAuth2.0认证授权三:使用JWT令牌

    历史文章 [Spring Security OAuth2.0认证授权一:框架搭建和认证测试] [Spring Security OAuth2.0认证授权二:搭建资源服务] 前面两篇文章详细讲解了如何基 ...

  5. 【django】用户登录模块实现步骤(二)之QQ登录工具AgentLogin和通过OAuth2.0认证获取openid【33】

    一.QQ登录工具AgentLogin 1.AgentLogin介绍 ⽬前只⽀持 腾讯QQ,微信,微博的第三⽅登录 该⼯具封装了QQ登录时对接QQ互联接⼝的请求操作.可⽤于快速实现QQ登录功能. 2.A ...

  6. Spring Security OAuth2.0认证授权五:用户信息扩展到jwt

    历史文章 [Spring Security OAuth2.0认证授权一:框架搭建和认证测试] [Spring Security OAuth2.0认证授权二:搭建资源服务] [Spring Securi ...

  7. 如何支持微软邮箱OAuth2.0认证

    近期收到部分使用微软邮箱的客户反映,在EDI系统中无法连接到他们的企业邮箱中,连接过程中报错: IMAP protocol error. 1 NO LOGIN failed-,经确认是微软停用了邮箱的 ...

  8. C# 网络编程之豆瓣OAuth2.0认证具体解释和遇到的各种问题及解决

            近期在帮人弄一个豆瓣API应用,在豆瓣的OAuth2.0认证过程中遇到了各种问题,同一时候自己须要一个个的尝试与解决,终于完毕了豆瓣API的訪问.作者这里就不再吐槽豆瓣的认证文档了,毕 ...

  9. C# 网络编程之豆瓣OAuth2.0认证详解和遇到的各种问题及解决

            最近在帮人弄一个豆瓣API应用,在豆瓣的OAuth2.0认证过程中遇到了各种问题,同时自己需要一个个的尝试与解决,最终完成了豆瓣API的访问.作者这里就不再吐槽豆瓣的认证文档了,毕竟人 ...

最新文章

  1. (十二)企业级java springcloud b2bc商城系统开源源码二次开发-断路器监控(Hystrix Dashboard)...
  2. 提取图像数据的特征,让机器“看见”
  3. Codeforces Round #674 (Div. 3)
  4. maven java1.7_本周Java技巧#7 – Maven慢吗?
  5. mysql dump 1017_MySQL数据库导出 - Can't Wait Any Longer - OSCHINA - 中文开源技术交流社区...
  6. 《Python Cookbook 3rd》笔记(5.11):文件路径名的操作
  7. linux ip 访问记录,linux 精确记录用户IP以及用户操作命令
  8. 【Redis】redis 主从复制
  9. python123m与n的数学运算_python小白进阶之路三——循环结构入门练习+Random库练习...
  10. JavaWeb——eclipse与tomcat环境配置
  11. jmeter配置元件之计数器
  12. pg数据库表接口和数据导出
  13. C#6.0VISUALSTUDIO 2015 C#入门经典 第7版pdf
  14. 怎么将服务器中图片显示出来,服务器显示图片
  15. iOS迅雷V6.01更新,变化重大丨附下载地址
  16. mysql 误删除数据恢复
  17. 10008---光环效应
  18. JZOJ7月28日提高组反思
  19. openwrt + dnsmasq + anti-AD 两步搞定广告屏蔽
  20. Python-3:循环-练习

热门文章

  1. 100道Java实习生需要掌握的面试问题
  2. js实现飞机大战小游戏
  3. Intel Tick-Tock
  4. CodeSmith 4 Release 注册破解序列号注册码方法
  5. MSA应用――MSA手册第四版的新亮点
  6. [JVM] java虚拟机内存管理机制及垃圾收集
  7. 旺店通·企业奇门与金蝶云星空对接集成查询货品档案连通物料新增(旺店通物料对接金蝶物料)
  8. WPF自定义列中按钮的IsEnabled属性根据列中的值的不同动态赋值
  9. 达内出来的混得怎么样了_大学经验丨计算机专业学生,应该怎么样才不会沦为普通程序员?...
  10. 如何解决win10网络出现叹号,但是能连网问题