实战电商后端系统(二)—— 将OAuth2认证和权限信息存入MySQL数据库

五分钟带你玩转oauth2(四)认知oauth2表结构,五步搞定Java开发环境部署 由于文案过于长,在此就不一一介绍了,这份Java后端架构进阶笔记内容包括:Java集合,JVM、Java并发、微服务、SpringNetty与 RPC 、网络、日志 、Zookeeper 、Kafka 、RabbitMQ 、Hbase 、MongoDB、Cassandra 、Java基础、负载均衡、数据库、一致性算法、Java算法、数据结构、分布式缓存等等知识详解。本知识体系适合于所有Java程序员学习,关于以上目录中的知识点都有详细的讲解及介绍,掌握该知识点的所有内容对你会有一个质的提升, 阅读详情

前言

本系统技术栈用到了Dubbo、Zookeeper、SpringBoot、Oauth2、Swagger、Nginx,项目刚开始起步,每完成一个大功能都会专门写一篇博文来记录技术细节以及遇到的技术难点,如项目中有哪些设计或者架构不太正确的地方,请大家在留言区中提出,互相学习~

上一章中,已经搭建好了项目的基础环境,则本文章则将OAuth2和MySQL集成起来,方便在认证和授权时能从MySQL数据库中读取client信息以及权限信息。同时,还新添加了一种授权模式:Authorization_code。

正文

一、关键表结构

表oauth_client_details

CREATE TABLE `oauth_client_details` (
  `client_id` varchar(128) NOT NULL,
  `resource_ids` varchar(256) DEFAULT NULL,
  `client_secret` varchar(256) DEFAULT NULL,
  `scope` varchar(256) DEFAULT NULL,
  `authorized_grant_types` varchar(256) DEFAULT NULL,
  `web_server_redirect_uri` varchar(256) DEFAULT NULL,
  `authorities` varchar(256) DEFAULT NULL,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` varchar(4096) DEFAULT NULL,
  `autoapprove` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

需要注意的是,这里client_secret是要存加密过后的值。

表oauth_client_token

CREATE TABLE `oauth_client_token` (
  `token_id` varchar(256) DEFAULT NULL,
  `token` blob,
  `authentication_id` varchar(128) NOT NULL,
  `user_name` varchar(256) DEFAULT NULL,
  `client_id` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`authentication_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

表tb_user

CREATE TABLE `tb_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(64) NOT NULL COMMENT '密码,加密存储',
  `phone` varchar(20) DEFAULT NULL COMMENT '注册手机号',
  `email` varchar(50) DEFAULT NULL COMMENT '注册邮箱',
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`) USING BTREE,
  UNIQUE KEY `phone` (`phone`) USING BTREE,
  UNIQUE KEY `email` (`email`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8 COMMENT='用户表';

表tb_role

CREATE TABLE `tb_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `parent_id` bigint(20) DEFAULT NULL COMMENT '父角色',
  `name` varchar(64) NOT NULL COMMENT '角色名称',
  `enname` varchar(64) NOT NULL COMMENT '角色英文名称',
  `description` varchar(200) DEFAULT NULL COMMENT '备注',
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8 COMMENT='角色表';

表tb_permission

CREATE TABLE `tb_permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `parent_id` bigint(20) DEFAULT NULL COMMENT '父权限',
  `name` varchar(64) NOT NULL COMMENT '权限名称',
  `enname` varchar(64) NOT NULL COMMENT '权限英文名称',
  `url` varchar(255) NOT NULL COMMENT '授权路径',
  `description` varchar(200) DEFAULT NULL COMMENT '备注',
  `created` datetime NOT NULL,
  `updated` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8 COMMENT='权限表';

表tb_role_permission

CREATE TABLE `tb_role_permission` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `role_id` bigint(20) NOT NULL COMMENT '角色 ID',
  `permission_id` bigint(20) NOT NULL COMMENT '权限 ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=48 DEFAULT CHARSET=utf8 COMMENT='角色权限表';

二、集成MySQL来获取授权信息

2.1 添加数据相关驱动以及插件依赖

添加数据库驱动以及tk mybatis插件

		<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>

添加HikariCP连接池

        <dependency>
            <groupId>com.zaxxer</groupId>
            <artifactId>HikariCP</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
            <exclusions>
                <!-- 排除 tomcat-jdbc 以使用 HikariCP -->
                <exclusion>
                    <groupId>org.apache.tomcat</groupId>
                    <artifactId>tomcat-jdbc</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

三、配置OAuth2认证服务器相关配置

3.1 配置认证服务器相关配置
    @Bean
    public ClientDetailsService jdbcClientDetailsService() {
        // 基于JDBC实现,需要实现在数据库配置客户端信息以及密码加密方式
        JdbcClientDetailsService detailsService = new JdbcClientDetailsService(dataSource);
        detailsService.setPasswordEncoder(passwordEncoder);
        return detailsService;
    }
  

这里的ClientDetailsService是OAuth2用于读取认证信息的服务,默认用的是InMemoryClientDetailsService,即将客户端信息存储到内存中。

声明好了ClientDetailsService之后,就要将其配置进OAuth2中替换InMemoryClientDetailsService。

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 从数据库中读取客户端配置
        clients.withClientDetails(jdbcClientDetailsService());
	}

这样,认证相关的配置就就配完了,完整配置如下:

AuthorizationServerConfigurerAdapter

package com.bruis.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
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.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
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.redis.RedisTokenStore;

import javax.sql.DataSource;
import java.util.UUID;


/**
 * @author LuoHaiYang
 *
 * 开启认证服务器
 *
 */
@Configuration
@EnableAuthorizationServer
// 开启权限控制
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    /**
     * 设置jwt加密key
     */
    private static final String JWT_SIGNING_KEY = "jwt_MC43A6m0Xt9jUIV";

    /**
     * 认证方式
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    /**
     * 自定义用户服务
     */
    @Autowired
    private UserDetailsService userDetailsService;
	
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Autowired
    private DataSource dataSource;

    /**
     * 配置客户端对应授权方式及客户端密码
     * 当前使用内存模式
     *
     * withClient + secret需要进行base64为加密:
     *
     * 明文:bruis:123456    BASE64:xxx
     *
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 从数据库中读取客户端配置
        clients.withClientDetails(jdbcClientDetailsService());
		/*
        clients.inMemory()
                .withClient("bruis")
                .secret(passwordEncoder.encode("123456"))
                .authorizedGrantTypes("authorization_code","password", "refresh_token")
                .scopes("all")
                .redirectUris("http://www.baidu.com");
				*/
                // 关闭授权确认步骤
                //.autoApprove(false);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore())
                // 配置密码模式需要制定认证器
                .authenticationManager(authenticationManager)
                .accessTokenConverter(accessTokenConverter())
                // 支持GET  POST  请求获取token
                .allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
                // 必须注入userDetailsService否则根据refresh_token无法加载用户信息
                .userDetailsService(userDetailsService)
                // .exceptionTranslator(customWebResponseExceptionTranslator)
                // 开启刷新token
                .reuseRefreshTokens(true);
    }

    /**
     * 认证服务器的安全配置
     *
     * @param security
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")
                //isAuthenticated():排除anonymous   isFullyAuthenticated():排除anonymous以及remember-me
                .checkTokenAccess("isAuthenticated()")
                //允许表单认证
                .allowFormAuthenticationForClients();
    }


    /**
     * jwt令牌增强,添加加密key
     */
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        // 使用OAuth2默认的JwtAccessTokenConverter
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        // 密钥加强
        converter.setSigningKey(JWT_SIGNING_KEY);
        return converter;
    }

    /**
     * 使用JWT存储令牌信息
     * @return
     */
    @Bean
    public TokenStore tokenStore() {
        RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);
        // 解决每次生成的 token都一样的问题
        redisTokenStore.setAuthenticationKeyGenerator(oAuth2Authentication -> UUID.randomUUID().toString());
        return redisTokenStore;
    }

    /**
     * token认证服务
     */
    @Bean
    public ResourceServerTokenServices tokenService() {
        // 授权服务和资源服务在统一项目内,可以使用本地认证方式,如果再不同工程,需要使用远程认证方式
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }

    @Bean
    public ClientDetailsService jdbcClientDetailsService() {
        // 基于JDBC实现,需要实现在数据库配置客户端信息以及密码加密方式
        JdbcClientDetailsService detailsService = new JdbcClientDetailsService(dataSource);
        detailsService.setPasswordEncoder(passwordEncoder);
        return detailsService;
    }

}
3.2 配置WebSecurityConfigurerAdapter

对于WebSecurityConfigurerAdapter的配置,这里需要申明数据源为HikariCP即可。

完整配置如下

WebSecurityConfig

package com.bruis.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
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.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.sql.DataSource;


/**
 * @author LuoHaiYang
 */
@Order(2)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    /**
     * 自定义用户服务类、用于用户名、密码校验、权限授权
     */
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    /**
     * 将 check_token 暴露出去,否则资源服务器访问时报403错误
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/oauth/check_token");
    }

    /**
     * 密码加密策略
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 将认证管理器注入SpringIOC容器中,用于密码模式
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * @Primary表示的是dataSource的bean采用DataSourceBuilder.create().build()返回的实例。
     * @return
     */
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        // 配置数据源(注意,我使用的是 HikariCP 连接池),以上注解是指定数据源,否则会有冲突
        return DataSourceBuilder.create().build();
    }
}

四、配置资源服务器

4.1 添加autoconfigure依赖

引入spring-security-oauth2-autoconfigure,用于资源服务器的自动配置

        <!-- 用于资源服务器的自动配置 -->
        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.2.RELEASE</version>
            <scope>compile</scope>
        </dependency>

引入这个autoconfigure的作用是在配置文件中,定义client、secret、authorize以及access_token的uri时,能够配置到OAuth2资源服务器配置类对象中。

对于本系统,gateway网关服务是作为一个资源对外开放的,所以需要引入autoconfigure,然后在配置文件中配置client、secret等配置。

在gateway服务中的application.properties文件中,添加如下配置:

# oauth2
security.oauth2.client.client-id=client
security.oauth2.client.client-secret=secret
security.oauth2.client.access-token-uri=http://localhost:8902/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8902/oauth/authorize
security.oauth2.resource.token-info-uri=http://localhost:8902/oauth/check_token
4.2 添加权限控制

@PreAuthorize

添加权限控制有两种方式,一种是在controller层使用注解:@PreAuthorize(“hasAuthority(‘SystemOrder’)”) 定义访问权限。

值得注意的是,@PreAuthorize可以修饰controller类以及controller方法。

在ResourceServerConfigure配置类中添加权限控制

@Override
    public void configure(HttpSecurity http) throws Exception {
        // 警用csrf,使用跨域
        http.csrf().disable()            
                .exceptionHandling()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/order/**").hasAuthority("SystemContent")                
                .antMatchers("/webjars/**", "/resources/**", "/swagger-ui.html"
                        , "/swagger-resources/**", "/v2/api-docs", "index.html").permitAll()
                .anyRequest().authenticated();
    }

五、效果展示

5.1 授权码模式

通过授权码模式去获取token,然后访问受保护的资源。

先看下oauth_client_details表的记录,client_id为client,client_secret为secret(数据库中以加密形式存储),scope为app,authorized_grant_types为authorization_code和password两种模式,而回调地址为 http://www.baidu.com。
在这里插入图片描述
通过访问:

http://localhost:8902/oauth/authorize?client_id=client&response_type=code

会首先跳转到OAuth2默认的login页面进行身份认证。

在这里插入图片描述
输入用户密码(admin/123456),就会跳转回 /oauth/authorize页面
在这里插入图片描述
这个页面也是OAuth2默认的授权页面(可以自定义,后面空了会写一个关于SpringSecurity和OAuth2底层原理的专栏,然后会介绍如何自定义OAuth2默认的login页面以及Approval页面)。

点击Approve进行确认授权,等页面重定向到百度首页后,会发现url中包含了一个code的值:VLgtje,这样我们就可以拿着这个code值去进行token的获取。
在这里插入图片描述
这里需要注意一下,对于/oauth/token的调用,需要传入 client_id和client_secret,在OAuth2中有两种方式传入,一种是以headers的形式传入经过加密的client_id和client_secret;另外一种方式就是在URL中以 client_id:client_secret的方式传入,具体示例如下:

以headers的方式传入

在这里插入图片描述
请求结果如下:
在这里插入图片描述

以 client_id:client_secret@的方式在URL中传入

由于code用过一次就不能再用了,所以要重新授权一次来演示。
重新请求的code如下:
在这里插入图片描述
效果如下:
在这里插入图片描述

5.2 密码模式

通过密码模式去获取tokne,然后访问受保护的资源。

在这里插入图片描述
密码模式的client_id和clinet_secret两种方式都可以,这里就不再赘述了。

5.3 访问受保护的资源服务

不管是通过密码模式还是授权码模式,最终的目的都是为了拿token,拿到token之后就有资格去访问受保护的资源服务了。
在本系统中,gateway就相当于一个资源服务,下面来尝试访问gateway暴露的接口。

在这里插入图片描述
在这里插入图片描述
然后再访问当前用户
在这里插入图片描述
可见,用户认证信息就是从数据库中读出的数据。

搞定…

下面贴上github源码地址,本篇文章对应的项目是在 v0.0.3分支上,数据库脚本以及nginx配置文件在项目的others目录中,有需要的读者在切换到该分支上进行操作即可。觉得博主写的不错,关注、点赞、star三连。。。

https://github.com/coderbruis/Distributed-mall

相关文章

Spring Security OAuth2实战:构建微服务统一认证与JWT授权中心 在微服务架构中,认证与授权是保障系统安全的核心环节。其基本原理是通过一个独立的认证中心统一管理用户身份,避免各服务重复实现登录逻辑。OAuth 2.0作为行业标准授权框架,定义了资源所有者、客户端、授权服务器和资源服务器四种角色,通过授权码等模式安全地颁发访问令牌。JWT(JSON Web Token)因其自包含、无状态和易于验证的特性,成为分布式系统中令牌载体的主流选择,它能有效减少服务间网络调用,提升性能。结合Spring Security这一强大的安全框架,可以快速构建一套生产级的统一认证授权方案,实 阅读详情

相关推荐

技术小白如何用腾讯云开发+Python打造电商数据管理系统

在当今数据驱动的商业环境中,数据处理与自动化管理已成为提升运营效率的关键。其核心原理在于通过API接口实现多源数据的自动采集,并利用编程语言进行清洗、整合与分析,最终通过可视化界面呈现业务洞察。这项技术的价值在于能够将业务人员从繁琐的手工数据整理中解放出来,实现数据驱动的精准决策。典型的应用场景包括电商运营、独立站管理以及小型团队的内部数据看板搭建。本文以Shopify电商数据管理为例,详细阐述了如何利用腾讯云开发这一低代码平台结合Python的pandas等库,构建一个从数据拉取、清洗、存储到分析可视化的

weixin_30279315的博客 369

SpringBoot OAuth2.0实战:从零构建安全认证服务

本文详细介绍了如何使用SpringBoot和OAuth2.0构建安全认证服务,涵盖从基础环境准备到核心配置、资源服务器实战、深度权限控制及生产环境优化等全流程。通过实战案例和代码示例,帮助开发者快速掌握OAuth2.0认证管理技术,提升系统安全性。

weixin_29230773的博客 81

【花艺电商】SpringBoot集成MyBatis-Plus、Swagger2、SpringSecurity、OAuth2等技术整合开发

这个项目主要使用了和等技术,实现了用户登录、购物车、订单生成、支付等功能,并使用了模板引擎搭建了前端页面。:我们使用了Spring Security来处理用户的登录验证和权限控制。用户在登录时,Spring Security会对用户的用户名和密码进行验证,验证通过后,会生成一个包含用户信息和权限的安全上下文,用于后续的权限控制。:我们集成了MyBatis-Plus,它提供了丰富的CRUD操作,可以方便地对数据库进行操作。

SAME_LOVE的博客 1533

oauth2.0 mysql表设计_OAuth2.0系列之信息数据库存储实践(六)

@1、OAuth2.0信息存储方式在前面文章中我们学习了OAuth2的一些基本概念,对OAuth2有了基本的认识,也对OAuth2.0的几种授权模式进行了实践,比如授权码模式在前面的学习中,我们配置客户端信息,一般会如下配置,如果有多个客户端的话,就复制一遍,修改一些参数,很显然,这种在生产环境是不适应的,所以Spring Security OAuth2是有提供几种存储方式的,默认是基于内存存储@...

weixin_35822534的博客 1221

解决用VScode写中文注释,Vivado打开之后是乱码的方法

这样就解决了中文注释乱码的问题,此外如果使用notepad++写verilog代码的话直接在notepad++上面将编码格式改为ANSI格式即可,更加方便快捷,所以此方法仅针对习惯用VScode写Verilog的同学,如果有其他好办法的话欢迎评论区补充。首先,VScode中的中文默认编码格式是UTF-8,然后Vivado的编码格式是vivado 默认的应该是ANSI编码格式,刚开始我先按照网上说明的,将VScode中的编码格式改为GBK格式(点击右下角->点击通过编码保存)。

weixin_50573305的博客 5809

车载以太网SOMEIP入门必看:从服务发现到事件订阅,一次搞懂三种核心通信模式(附报文实例)

本文深入解析车载以太网SOME/IP的三种核心通信模式:服务发现、方法调用和事件订阅,通过真实报文实例和仿真工具演示,帮助开发者快速掌握这一关键技术。文章特别强调服务发现机制的基础作用,并详细介绍了Request/Response与Fire&Forget两种方法调用模式的应用场景,为智能汽车网络通信开发提供实用指南。

weixin_30955617的博客 111

Spring Security OAuth2四种授权模式总结 - Mysql存储客户端信息和令牌(八)

本篇将客户端信息、令牌、用户身份信息等都存到Mysql数据库中。本篇环境及代码是在上一篇基础之上,这里只记录主要的改动部分。

FAIRYTAIL的博客 1598

告别ArcGIS小红叉:从‘无法验证登录信息’到成功连接在线资源的完整排错记录

本文详细记录了从Windows便签的网络错误到ArcGIS连接问题的完整排错过程。通过分析代理服务器、DNS配置和系统网络设置,解决了ArcGIS无法验证登录信息的问题,提供了实用的网络优化方案和技术排错思路。

weixin_26800111的博客 389

spring security oauth2 默认User Approval页面,定制方法

授权入口 org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint private String userApprovalPage = "forward:/oauth/confirm_access"; // We need explicit approval from the user. private ModelAndView getUserApprovalPageResponse(Map<String,

路过君的博客 1418

TPS563201DDCR电路翻车实录:从原理图到PCB,我踩过的5个坑及补救方法

本文详细记录了使用TPS563201DDCR电源芯片设计电路时遇到的5个常见问题及解决方案,包括EN引脚配置、BST电容选型、反馈网络设计、PCB布局优化以及散热处理。通过实际案例和数据分析,帮助工程师避免类似错误,提升电源模块的可靠性和效率。

weixin_42532938的博客 527

深入理解C++23的Deducing this特性(上):基础概念与语法详解

C++23标准中引入的"Deducing this"特性是一项重大革新,它不仅改变了我们编写成员函数的方式,还为模板元编程和设计模式实现带来了新的可能。

weixin_61470881的博客 1332

springboot+springsecurity+oauth2整合(并用mysql数据库实现持久化客户端数据)

springboot+springsecurity+oauth2整合(并用mysql实现持久化) 本文主要讲的是,实现oauth2的工作流程,需要对oauth2.0概念有一定的基础知识了解。阅读前请学习oauth2.0的理论知识。文末有此项目代码地址。 介绍 AuthorizationServer的搭建 创建Client 请求access_token 刷新access_token 介......

Victor_An的博客 2万+

事件驱动的 SAP 工作流:从 BOR 事件到 Event Linkage 的落地与排障全景图

摘要: SAP工作流中的Event是业务对象状态变化的系统广播机制,如发票录入、采购订单释放等事件。通过事件驱动,业务程序与流程引擎解耦,业务只需发布事件,流程引擎负责后续处理。文章详细解析了SAP工作流事件的完整链路,包括事件定义、触发机制、事件容器传递、SWE2配置的关键作用,以及事件不触发时的排查方法。重点介绍了事件在启动流程、终止任务、等待步骤和主动创建中的应用,并结合采购订单审批案例说明事件的实际使用场景和配置要点。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 187

实战电商后端系统(三)—— 以vue-element-admin为基础的前端项目对接后端接口

文章目录前言正文1. 项目初始化2. 精简项目3. 替换mock接口,对接后端接口3.1 修改/src/api/user.js3.2 修改项目中请求方式4. 效果展示参考相关文章 前言 本系统技术栈用到了Dubbo、Zookeeper、SpringBoot、Oauth2、Swagger、Nginx,项目刚开始起步,每完成一个大功能都会专门写一篇博文来记录技术细节以及遇到的技术难点,如项目中有哪些设计或者架构不太正确的地方,请大家在留言区中提出,互相学习~ 前两篇博文已经详细讲解了如何搭建项目基础架构以及My

你要悄悄的拔尖,然后惊艳所有人 3604

使用conda环境python3.13和python3.12下安装vllm过程记录

使用conda环境python3.13和python3.12下安装vllm过程记录

没刮胡子的程序员专栏 884

华为OD机考2025C卷 - 精准核酸检测(Java & Python& JS & C++ & C语言)

华为OD机考2025C卷 - 精准核酸检测,提供在线OJ Java & Python& JS & C++ & C

算法大师! 2881

电商网站如何用OAuth2实现第三方登录?实战案例

通过这个项目,我深刻体会到了OAuth2在实际业务中的应用价值。它不仅简化了用户登录流程,还为后续的用户数据管理提供了便利。对于电商网站来说,实现第三方登录功能几乎是标配,而OAuth2是实现这一功能的最佳选择。如果你也在开发类似的功能,建议先理清业务流程,然后再分模块实现。遇到问题时,多查阅官方文档和社区讨论,大部分问题都能找到解决方案。

GreyWolf12的博客 635

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Spring Boot HTTP认证实战:从基础协议到JWT与OAuth2集成

认证是Web应用安全的第一道防线,它通过验证用户身份来保护资源访问。其原理基于HTTP协议标准或扩展的令牌机制,在服务端构建安全链路以确认请求者身份。这一技术的核心价值在于为应用提供可靠的身份识别与访问控制基础,是现代系统实现用户登录、API保护和第三方集成不可或缺的环节。在Spring Boot开发中,借助Spring Security框架,开发者可以高效实现表单登录、HTTP Basic、JWT等主流认证方案,并能集成OAuth2.0支持第三方登录。本文聚焦于**JWT**和**OAuth2.0**这两

weixin_33875564的博客 391

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

电商系统中的Spring Security认证实战

这里特别要注意Spring Security的版本选择,我们使用的是5.7.x版本,这个版本在安全性和易用性上都有不错的表现。这个平台内置了Spring Boot和Spring Security环境,支持一键部署,可以快速验证各种认证方案。我在测试阶段就用了这个平台,发现它的实时预览和部署功能特别方便,省去了本地搭建环境的麻烦。通过Spring Security的灵活配置,我们成功实现了多种登录方式和细粒度的权限控制。通过这个项目,我深刻体会到Spring Security的强大和灵活。

GoldenleafLynx28的博客 311

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Keycloak实战指南:从零构建企业级身份认证系统

本文详细介绍了Keycloak作为企业级身份认证系统的实战指南,涵盖从零搭建到高级功能的全面解析。通过单点登录(SSO)、集中式用户管理和多因素认证(MFA)等核心功能,帮助企业快速构建安全、高效的身份认证体系。特别适合需要统一身份管理的金融机构、电商平台等企业场景。

cuda7parallel的博客 912

3步构建企业级认证系统实战指南:从0到1搭建安全认证中心

在当今分布式系统架构中,身份认证与授权是保障系统安全的第一道防线。随着微服务架构的普及,传统的单点认证方式已无法满足多系统集成需求。本文将通过"问题-方案-实践"三段式框架,带你从零开始构建一个符合OAuth2.0协议规范的企业级认证中心,解决分布式环境下的身份统一管理难题。 ## 一、问题:分布式系统认证的核心挑战 随着企业IT架构向微服务转型,认证系统面临三大核心挑战: **身份统一难题

gitblog_00438的博客 405

【Java电商系统实战】:从零搭建高并发电商平台的5大核心架构设计

掌握高并发电商系统设计难题,本文基于Java电商系统实战经验,详解微服务架构、分布式缓存、订单与支付系统等5大核心设计。适用于中大型电商平台搭建,提升系统性能与稳定性,值得收藏。

ProceGlow的博客 490

告别内存存储:Spring Authorization Server如何用MySQL持久化客户端与授权信息

本文深入探讨了Spring Authorization Server在生产环境中如何通过MySQL实现客户端与授权信息的持久化,解析了三张核心表的设计哲学及最佳实践。通过对比内存存储与数据库存储的性能差异,展示了MySQL持久化在企业级应用中的可行性与优势,并提供了安全增强配置、高可用架构设计等实战建议。

weixin_33739523的博客 502

7步构建企业级数据库管理工具选型框架:Chat2DB深度技术解析与实战指南

在当今数据驱动的商业环境中,企业级数据库工具选型已成为技术决策者面临的核心挑战之一。随着数据量的爆炸式增长和业务复杂性的提升,传统的数据库管理工具已难以满足现代企业的需求。Chat2DB作为一款AI驱动的数据库客户端和SQL工作空间,为技术决策者提供了一个创新的企业级数据库管理工具选型框架,帮助团队在开源与商业版本之间做出明智选择。 ## 1. 核心理念解析:从设计哲学到技术愿景 Chat2D

gitblog_00577的博客 456

电商云平台系统的设计与实现

总的来说,电商云平台系统的架构设计应该充分考虑到系统的性能、扩展性、安全性等多个方面的因素。只有在系统的设计和实现过程中充分考虑这些因素,才能构建出满足电商市场需求的高效、稳定和安全的系统。在实际开发中,我们需要遵循敏捷开发的原则,逐步实现系统的各个模块,并进行单元测试和集成测试,确保系统的稳定性和功能完备性。订单管理:系统需要记录每个订单的基本信息、订单状态、订单总价等信息,并在订单完成后更新销售量、库存量等相关数据。用户管理:系统需要记录用户的基本信息、订单记录等,以及处理用户的注册、登录等操作。

qq_33665793的博客 2138

OAuth 2 实战避坑指南:从 redirect_uri_mismatch 到 token 泄露防护

OAuth 2 不是登录协议,而是一套基于角色分离的授权委托机制,其核心在于资源所有者、客户端、授权服务器与资源服务器四者间的可信协作。理解 access_token 的临时性、scope 的权限约束性及 refresh_token 的安全存储要求,是保障系统合规与稳定的关键。技术价值体现在细粒度权限控制、跨域服务解耦与用户隐私保护;典型应用场景包括第三方账号登录、SaaS 应用集成、IoT 设备授权等。本文聚焦真实工程中高频报错(如 redirect_uri_mismatch、invalid_client

weixin_30263277的博客 386
上一篇: 后端学习Vue系列之——Vuex
下一篇: 实战电商后端系统(三)—— 以vue-element-admin为基础的前端项目对接后端接口
CoderBruis
博客等级 码龄10年 4444粉丝 102原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值