文章目录

  • 设置通用父工程依赖
  • 构建eureka注册中心
  • 构建认证授权服务
    • 配置文件设置
    • Security配置类
    • 授权服务配置类
    • 登录实现
  • 测试验证

设置通用父工程依赖

在微服务构建中,我们一般用一个父工程来通知管理依赖的各种版本号信息。父工程pom文件如下:

<?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>com.zjq</groupId><artifactId>oauth2-demo</artifactId><packaging>pom</packaging><version>1.0-SNAPSHOT</version><modules><module>commons</module><module>ms-gateway</module><module>ms-oauth2-server</module><module>ms-registry</module></modules><!-- 可以集中定义依赖资源的版本信息 --><properties><spring-boot-version>2.3.7.RELEASE</spring-boot-version><spring-cloud-version>Hoxton.SR9</spring-cloud-version><lombok-version>1.18.16</lombok-version><commons-lang-version>3.11</commons-lang-version><mybatis-starter-version>2.1.3</mybatis-starter-version><mysql-version>8.0.22</mysql-version><swagger-starter-version>2.1.5-RELEASE</swagger-starter-version><hutool-version>5.4.7</hutool-version><guava-version>20.0</guava-version><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><!-- 集中定义依赖,不引入 --><dependencyManagement><dependencies><!-- spring boot 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot-version}</version><type>pom</type><scope>import</scope></dependency><!-- spring cloud 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud-version}</version><type>pom</type><scope>import</scope></dependency><!-- lombok 依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok-version}</version></dependency><!-- common-lang3 依赖 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>${commons-lang-version}</version></dependency><!-- mybatis 依赖 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis-starter-version}</version></dependency><!-- swagger 依赖 --><dependency><groupId>com.battcn</groupId><artifactId>swagger-spring-boot-starter</artifactId><version>${swagger-starter-version}</version></dependency><!-- mysql 依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-version}</version></dependency><!-- hutool 依赖 --><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>${hutool-version}</version></dependency><!-- guava 依赖 --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>${guava-version}</version></dependency></dependencies></dependencyManagement><!-- 集中定义项目所需插件 --><build><pluginManagement><plugins><!-- spring boot maven 项目打包插件 --><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></pluginManagement></build></project>

构建eureka注册中心

在SpringCloud微服务体系中服务注册中心是一个必要的存在,通过注册中心提供服务的注册和发现。具体细节可以查看我之前的博客,这里不再赘述。我们开始构建一个eureka注册中心,对应的yml配置文件如下:

server:port: 8080spring:application:# 应用名称name: ms-registry# 配置 Eureka Server 注册中心
eureka:client:register-with-eureka: falsefetch-registry: falseservice-url:defaultZone: http://localhost:8080/eureka/logging:pattern:console: '%d{HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n'

对应的项目启动类代码如下:

package com.zjq.msregistry;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/*** 注册中心* @author zjq*/
//启动 eureka注册中心服务端相关组件
@EnableEurekaServer
@SpringBootApplication
public class MsRegistryApplication {public static void main(String[] args) {SpringApplication.run(MsRegistryApplication.class, args);}}

至此,一个单体的服务注册中心搭建完成。

构建认证授权服务

上文我们已经完成了注册中心的搭建,接下来我们开始搭建认证授权中心。

配置文件设置

我们同样在父工程下面新建一个子工程,作为认证授权中心的微服务。对应的yml文件和pom文件配置如下:
application.yml

server:port: 8082 # 端口spring:application:name: ms-oauth2-server # 应用名# 数据库datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://127.0.0.1:3306/oauth2?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false# Redisredis:port: 6379host: localhosttimeout: 3000database: 1password: 123456# swaggerswagger:base-package: com.zjq.oauth2title: 认证服务API接口文档# Oauth2
client:oauth2:client-id: appId # 客户端标识 IDsecret: 123456 # 客户端安全码# 授权类型grant_types:- password- refresh_token# token 有效时间,单位秒token-validity-time: 3600refresh-token-validity-time: 3600# 客户端访问范围scopes:- api- all# 配置 Eureka Server 注册中心
eureka:instance:prefer-ip-address: trueinstance-id: ${spring.cloud.client.ip-address}:${server.port}client:service-url:defaultZone: http://localhost:8080/eureka/# Mybatis
mybatis:configuration:map-underscore-to-camel-case: true # 开启驼峰映射# 指标监控健康检查
management:endpoints:web:exposure:include: "*" # 暴露的端点logging:pattern:console: '%d{HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n'

pom.xml

<?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>oauth2-demo</artifactId><groupId>com.zjq</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>ms-oauth2-server</artifactId><dependencies><!-- eureka client --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!-- spring web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- spring data redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- mybatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- spring cloud security --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><!-- spring cloud oauth2 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><!-- commons 公共项目 --><dependency><groupId>com.zjq</groupId><artifactId>commons</artifactId><version>1.0-SNAPSHOT</version></dependency><!-- 自定义的元数据依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency></dependencies></project>

Security配置类

我们开始搭建Spring Security相关的配置类,具体配置类代码如下:

package com.zjq.oauth2.server.config;import cn.hutool.crypto.digest.DigestUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import javax.annotation.Resource;/*** Security 配置类* @author zjq*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {// 注入 Redis 连接工厂@Resourceprivate RedisConnectionFactory redisConnectionFactory;/*** 初始化 RedisTokenStore 用于将 token 存储至 Redis* @return*/@Beanpublic RedisTokenStore redisTokenStore() {RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);redisTokenStore.setPrefix("TOKEN:"); // 设置key的层级前缀,方便查询return redisTokenStore;}// 初始化密码编码器,用 MD5 加密密码@Beanpublic PasswordEncoder passwordEncoder() {return new PasswordEncoder() {/*** 加密* @param rawPassword 原始密码* @return*/@Overridepublic String encode(CharSequence rawPassword) {return DigestUtil.md5Hex(rawPassword.toString());}/*** 校验密码* @param rawPassword       原始密码* @param encodedPassword   加密密码* @return*/@Overridepublic boolean matches(CharSequence rawPassword, String encodedPassword) {return DigestUtil.md5Hex(rawPassword.toString()).equals(encodedPassword);}};}// 初始化认证管理对象@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}// 放行和认证规则@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests()// 放行的请求.antMatchers("/oauth/**", "/actuator/**").permitAll().and().authorizeRequests()// 其他请求必须认证才能访问.anyRequest().authenticated();}}

Security配置类主要完成以下配置:

  1. 注入 Redis 连接工厂
  2. 初始化 RedisTokenStore 用于将 token 存储至 Redis
  3. 初始化密码编码器,用 MD5 加密密码
  4. 初始化认证管理对象
  5. 设置放行和认证规则

授权服务配置类

配置完了security配置类后,我们开始编写授权服务配置类,授权服务配置类需要继承AuthorizationServerConfigurerAdapter并重写对应的方法,tips:idea子类重写父类快捷键是Ctrl+O,重写后的授权服务配置类如下:

package com.zjq.oauth2.server.config;import com.zjq.commons.model.domain.SignInIdentity;
import com.zjq.oauth2.server.service.UserService;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
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.store.redis.RedisTokenStore;import javax.annotation.Resource;
import java.util.LinkedHashMap;/*** 授权服务配置类* @author zjq*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {// RedisTokenSore@Resourceprivate RedisTokenStore redisTokenStore;// 认证管理对象@Resourceprivate AuthenticationManager authenticationManager;// 密码编码器@Resourceprivate PasswordEncoder passwordEncoder;// 客户端配置类@Resourceprivate ClientOAuth2DataConfiguration clientOAuth2DataConfiguration;// 登录校验@Resourceprivate UserService userService;/*** 配置令牌端点安全约束** @param security* @throws Exception*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {// 允许访问 token 的公钥,默认 /oauth/token_key 是受保护的security.tokenKeyAccess("permitAll()")// 允许检查 token 的状态,默认 /oauth/check_token 是受保护的.checkTokenAccess("permitAll()");}/*** 客户端配置 - 授权模型** @param clients* @throws Exception*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient(clientOAuth2DataConfiguration.getClientId()) // 客户端标识 ID.secret(passwordEncoder.encode(clientOAuth2DataConfiguration.getSecret())) // 客户端安全码.authorizedGrantTypes(clientOAuth2DataConfiguration.getGrantTypes()) // 授权类型.accessTokenValiditySeconds(clientOAuth2DataConfiguration.getTokenValidityTime()) // token 有效期.refreshTokenValiditySeconds(clientOAuth2DataConfiguration.getRefreshTokenValidityTime()) // 刷新 token 的有效期.scopes(clientOAuth2DataConfiguration.getScopes()); // 客户端访问范围}/*** 配置授权以及令牌的访问端点和令牌服务** @param endpoints* @throws Exception*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 认证器endpoints.authenticationManager(authenticationManager)// 具体登录的方法.userDetailsService(userService)// token 存储的方式:Redis.tokenStore(redisTokenStore);}}

上面用到的客户端配置类如下:

package com.zjq.oauth2.server.config;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 客户端配置类* @author zjq*/
@Component
@ConfigurationProperties(prefix = "client.oauth2")
@Data
public class ClientOAuth2DataConfiguration {// 客户端标识 IDprivate String clientId;// 客户端安全码private String secret;// 授权类型private String[] grantTypes;// token有效期private int tokenValidityTime;/*** refresh-token有效期*/private int refreshTokenValidityTime;/*** 客户端访问范围*/private String[] scopes;}

具体登录的方法实现:

登录实现

package com.zjq.oauth2.server.service;import com.zjq.commons.model.domain.SignInIdentity;
import com.zjq.commons.model.pojo.Users;
import com.zjq.commons.utils.AssertUtil;
import com.zjq.oauth2.server.mapper.UsersMapper;
import org.springframework.beans.BeanUtils;
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 javax.annotation.Resource;/*** 登录校验* @author zjq*/
@Service
public class UserService implements UserDetailsService {@Resourceprivate UsersMapper usersMapper;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {AssertUtil.isNotEmpty(username, "请输入用户名");Users users = usersMapper.selectByAccountInfo(username);if (users == null) {throw new UsernameNotFoundException("用户名或密码错误,请重新输入");}// 初始化登录认证对象SignInIdentity signInIdentity = new SignInIdentity();// 拷贝属性BeanUtils.copyProperties(users, signInIdentity);return signInIdentity;}}

UsersMapper:

package com.zjq.oauth2.server.mapper;import com.zjq.commons.model.pojo.Users;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;/*** 用户 Mapper* @author zjq*/
public interface UsersMapper {/**** 根据用户名 or 手机号 or 邮箱查询用户信息** @param account* @return*/@Select("select id, username, nickname, phone, email, " +"password, avatar_url, roles, is_valid from t_users where " +"(username = #{account} or phone = #{account} or email = #{account})")Users selectByAccountInfo(@Param("account") String account);}

用户实体:

package com.zjq.commons.model.pojo;import com.zjq.commons.model.base.BaseModel;
import lombok.Getter;
import lombok.Setter;/*** 用户实体类** @Author zjq* @Date 2022/10/12*/
@Getter
@Setter
public class Users extends BaseModel {// 主键private Integer id;// 用户名private String username;// 昵称private String nickname;// 密码private String password;// 手机号private String phone;// 邮箱private String email;// 头像private String avatarUrl;// 角色private String roles;}
package com.zjq.commons.model.base;import lombok.Getter;
import lombok.Setter;import java.io.Serializable;
import java.util.Date;/*** 实体对象公共属性** @Author zjq* @Date 2022/10/12*/
@Getter
@Setter
public class BaseModel implements Serializable {private Integer id;private Date createDate;private Date updateDate;private int isValid;}

到此,我们完成了认证授权服务构建,接下来我们进行测试验证:

测试验证

我们启动注册中心和认证授权微服务。访问注册中心:http://localhost:8080/
可以看到认证授权服务已经注册到注册中心。

接下来我们通过postman访问请求token测试:

Authorization请求头中配置,username和password,对应oauth客户端中的配置:

在body中配置请求参数,发起请求后返回如下:

在Redis中我们也可以看到生成的相关token配置:

至此,我们完成了认证授权中心的初步搭建。

本文内容到此结束了,
如有收获欢迎点赞

SpringCloud整合spring security+ oauth2+Redis实现认证授权相关推荐

  1. refreshtoken用mysql_「SpringCloud」 Spring Security OAuth2 Mysql管理在线Token

    原标题:「SpringCloud」 Spring Security OAuth2 Mysql管理在线Token 前言:Spring Cloud 分布式中的登录如何可视化的管理目前下发的令牌.使用情况. ...

  2. 【Spring Cloud Spring Security Oauth2】Spring Security Oauth2 + Redis + Gateway网关 + Mybatis + Mysql 整合

    目录 一.环境要求 二.源码下载地址 三.参考文献 四.项目预览截图说明 五.oauth2.0认证授权项目 5.1 POM依赖 5.2 yml配置及启动类 5.3 认证配置与资源配置 5.4 自定义U ...

  3. 从零开始超详细的Spring Security OAuth2.0实现分布式系统授权(注册中心+网关+认证授权服务(JWT令牌验证)+资源调用服务)

    文章目录 一.OAuth2.0 1.介绍 2.例子 3.执行流程 二.Spring Cloud Security OAuth2 1.环境介绍 2.认证流程 三.整合分布式项目 1.技术方案 2.项目结 ...

  4. Spring Security使用数据库登录认证授权

    一.搭建项目环境 1.创建 RBAC五张表 RBAC,即基于角色的权限访问控制(Role-Based Access Control),就是用户通过角色与权限进行关联. 在这种模型中,用户与角色之间,角 ...

  5. Spring Security | 轻松搞定认证授权~

    文章目录 一.Spring Security 简介 二.整合 Spring Security 1.创建项目,导入依赖 2.创建数据库,搭建环境 3.配置数据库 4.创建实体类 5.实现 UserMap ...

  6. Spring Security Oauth2 如何增加自定义授权模式

    在 oauth2 中已经默认有的授权模式中有4种: 授权码模式 隐式授权模式 密码模式 客户端模式 但是实际使用过程中万一我们要基于短信授权,或者基于token 直接授权该怎么办? 这里我们可以先看下 ...

  7. 微服务商城系统(十) Spring Security Oauth2 + JWT 用户认证

    文章目录 一.用户认证分析 1.认证 与 授权 2.单点登录 3.第三方账号登录 4.第三方认证 5.认证技术方案 6.Security Oauth 2.0 入门 7. 资源服务授权 (1)资源服务授 ...

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

    一. 前言 hi,大家好~ 好久没更文了,期间主要致力于项目的功能升级和问题修复中,经过一年时间这里只贴出关键部分代码的打磨,[有来]终于迎来v2.0版本,相较于v1.x版本主要完善了OAuth2认证 ...

  9. Spring Security Oauth2 JWT 实现用户认证授权功能

    Spring Security Oauth2 JWT 一 用户认证授权 1. 需求分析 1.1 用户认证与授权 什么是用户身份认证? 用户身份认证即用户去访问系统资源时系统要求验证用户的身份信息,身份 ...

最新文章

  1. c++ 哈希_详解Python中的可哈希对象与不可哈希对象(二)
  2. python可以做什么有趣的东西-Python 里itchat 模块能实现什么有趣的东西?
  3. macOS下加载动态库dylib报code signature invalid错误的解决办法
  4. 容器和容器镜像的区别,您真的了解吗
  5. .net core 使用RSA获取私钥证书并签名
  6. 7.25第一次组队赛
  7. 低代码开发是如何解决企业招聘技术人才难题?
  8. 计算机行政考试题库,2014香港特别行政区计算机等级考试试题 二级ACCESS考试题库...
  9. 从零开始学前端:CSS元素模式的转换和CSS三大特性 --- 今天你学习了吗?(CSS:Day12)
  10. asp.net mvc 路由检测工具
  11. 有没有网上python一对一-使用Python的Tornado框架实现一个一对一聊天的程序
  12. python运维平台开发_python运维平台的设计
  13. 安卓比较好的数独软件_有没有比较好的数独游戏APP?
  14. 为什么要数据归一化和归一化方法
  15. python logging动态变更输出日志文件名
  16. 树莓派系统搭建在PC虚拟机中
  17. 网络推广工作内容:自媒体运营的一天
  18. 【开发工具】IDEA Lua 开发环境配置(完整无错)
  19. 固本培元之二:字符串和转义符
  20. java基础之包_繁星漫天_新浪博客

热门文章

  1. 计算机网络技术的概况
  2. android 倒计 代码,2小时倒计时
  3. EP4CE115F29C7的VGA显示
  4. C语言 航班售票系统/航班管理系统
  5. UE4-(蓝图)第一百课 用.csv格式文件作为配置文件并获取、使用数据
  6. originlab设置_Origin修改默认字体,提高作图效率!
  7. 以《纪念碑谷》为例解析二维图像的视觉欺骗原理
  8. 游戏盾-一个让你放心的盾
  9. 什么是激光雷达的“发动机技术”?一文讲透行业技术壁垒
  10. 小米潘多拉路由器添加节点_腾讯网游加速器联手小米路由器,共创全场景游戏加速体验!...