springsecurity oauth2实现前后端分离项目的SSO技术点总结

2023-05-16

参考:

https://www.jianshu.com/p/b549220e7b34?ivk_sa=1024320u

一、基于cookie+session的SSO基本实现

1、认证中心的授权服务器配置

配置类继承AuthorizationServerConfigurerAdapter,解决可以将哪些资源进行授权、怎么授权的问题。

1)服务安全配置

授权服务相关的接口进行安全访问的相关设置,如/oauth/token_key,/oauth/token等。

public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.allowFormAuthenticationForClients()
        .tokenKeyAccess("isAuthenticated()");
}

2)客户端信息配置

加载注册的客户端信息,可以从数据库中加载。

@Bean
public ClientDetailsService inMemoryClientDetailsService() throws Exception {
	return new InMemoryClientDetailsServiceBuilder()
			// client oa application
			.withClient("client1")
			.secret(passwordEncoder.encode("client1_secret"))
			.scopes("all")
			.authorizedGrantTypes("authorization_code", "refresh_token")
			.redirectUris("http://client1.com/client1/login")
			.accessTokenValiditySeconds(7200)
            // 自动授权
			.autoApprove(true)

			.and()

			// client crm application
			.withClient("client2")
			.secret(passwordEncoder.encode("client2_secret"))
			.scopes("all")
			.authorizedGrantTypes("authorization_code", "refresh_token")
			.redirectUris("http://client2.com/client2/login")
			.accessTokenValiditySeconds(7200)
            // 自动授权
			.autoApprove(true)

			.and()
			.build();
} 
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
	clients.withClientDetails(inMemoryClientDetailsService());
}

3)服务端点token配置

配置token的管理器及存储器,存储方式可以是jwt、jdbc、redis。

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
				//指定token的管理器
	endpoints.accessTokenConverter(jwtAccessTokenConverter())
				//指定token的存储器
			.tokenStore(jwtTokenStore());
}

@Bean
public JwtTokenStore jwtTokenStore() {
	return new JwtTokenStore(jwtAccessTokenConverter());
}

@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
	JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
	jwtAccessTokenConverter.setSigningKey("123456");
	return jwtAccessTokenConverter;
}

2、认证中心的web安全配置

配置对用户的认证和对项目相关资源的访问配置,加载用户及权限,主要解决是谁和有哪些权限的问题。

1)认证管理配置

需要指定用户获取的服务,以及密码编码器。

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // 配置用户信息获取的服务,及密码编码器(用于将前端传过来的密码参数进行编码)
	auth.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
}

@Bean
@Override
public UserDetailsService userDetailsServiceBean() {
	Collection<UserDetails> users = buildUsers();

	return new InMemoryUserDetailsManager(users);
}

// 可以从数据库中进行获取
private Collection<UserDetails> buildUsers() {
	String password = passwordEncoder().encode("123456");

	List<UserDetails> users = new ArrayList<>();

	UserDetails user_admin = User.withUsername("admin").password(password).authorities("ADMIN", "USER").build();
	UserDetails user_user1 = User.withUsername("user1").password(password).authorities("USER").build();

	users.add(user_admin);
	users.add(user_user1);

	return users;
}

@Bean
public PasswordEncoder passwordEncoder() {
	return new BCryptPasswordEncoder();
}

2)http安全配置

指定表单登录、手机验证登录等方式,并配置对应的未登录认证的入口、登录成功和失败的处理器等。

自定义未登录认证入口,解决跳转到认证中心前端登录页面(需要由异常处理器进行处理)

@Component("unauthorizedEntryPoint")
public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        Map<String, String[]> paramMap = request.getParameterMap();
        StringBuilder param = new StringBuilder();
        paramMap.forEach((k, v) -> {
            param.append("&").append(k).append("=").append(v[0]);
        });
        param.deleteCharAt(0);
        String isRedirectValue = request.getParameter("isRedirect");
        if (!StringUtils.isEmpty(isRedirectValue) && Boolean.valueOf(isRedirectValue)) {
            response.sendRedirect("http://oauth.com/authPage/login?"+param.toString());
            return;
        }
		// 如果前端ajax请求兼容处理了登录页面的响应(即text/html,而非application/json,前端处理见5、客户端前端配置),
		// 可以不需要返回json结果,直接response.sendRedirect到登录界面,
        // 建议前端ajax兼容处理sendRedirect方式返回的页面,方便非ajax请求直接重定向到登录页面,
        // 因为在这里很难判断最原始的请求(客户端的前端请求)是否为ajax请求
        String authUrl = "http://oauth.com/auth/oauth/authorize?"+param.toString()+"&isRedirect=true";
        Result result = new Result();
        result.setCode(800);
        result.setData(authUrl);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter writer = response.getWriter();
        ObjectMapper mapper = new ObjectMapper();
        writer.print(mapper.writeValueAsString(result));
        writer.flush();
        writer.close();
    }
}

自定义登录成功处理

@Component("successAuthentication")
public class SuccessAuthentication extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter writer = response.getWriter();
        Result result = new Result();
        result.setCode(0);
        result.setMsg("成功");
        ObjectMapper mapper = new ObjectMapper();
        writer.println(mapper.writeValueAsString(result));
        writer.flush();
        writer.close();
    }
}

自定义登录失败处理

@Component("failureAuthentication")
public class FailureAuthentication extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        PrintWriter writer = response.getWriter();
        Result result = new Result();
        result.setCode(1000);
        result.setMsg("登录失败");
        ObjectMapper mapper = new ObjectMapper();
        writer.println(mapper.writeValueAsString(result));
        writer.flush();
        writer.close();
    }
}

http安全配置

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.cors().and().csrf().disable()
			.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint)
			.and()
			.authorizeRequests()
			.antMatchers("/login").permitAll()
			.anyRequest().authenticated()
			.and()
			.formLogin().successHandler(successAuthentication).failureHandler(failureAuthentication);
}

3)web安全配置

指定访问哪些资源的请求可以不需要进行认证。

@Override
public void configure(WebSecurity web) throws Exception {
	web.ignoring().antMatchers("/assets/**", "/css/**", "/images/**");
}

3、 认证中心跨域处理

从客户端的前端重定向到认证中心的授权服务/oauth/authorize,如果在nginx代理设置了跨域,则这个过滤器必须设置成无效,因为相同的跨域配置只能配置一次。

@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnProperty(prefix = "server.cors",name = "enable",havingValue = "true")//可让该filter失效,即不加载此filter
public class CORSFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        //允许所有的域访问,可以设置只允许自己的域访问
        response.setHeader("Access-Control-Allow-Origin", "*");
        //允许所有方式的请求
        response.setHeader("Access-Control-Allow-Methods", "*");
        //头信息缓存有效时长(如果不设 Chromium 同时规定了一个默认值 5 秒),没有缓存将已OPTIONS进行预请求
        response.setHeader("Access-Control-Max-Age", "3600");
        //允许的头信息
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }
}

4、客户端配置

1)启用SSO客户端

继承WebSecurityConfigurerAdapter,开启@EnableOAuth2Sso

@EnableOAuth2Sso
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.logout()
                .and()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }
}

2)配置OAUTH2服务相关配置

server:
  port: 8081
  servlet:
    context-path: /client1

security:
  oauth2:
    client:
      client-id: client1
      client-secret: client1_secret
      access-token-uri: http://oauth.com/auth/oauth/token
      user-authorization-uri: http://oauth.com/auth/oauth/authorize
    resource:
      jwt:
        key-uri: http://oauth.com:8080/auth/oauth/token_key

5、认证中心前端设置

如果客户端的前端ajax重定向到认证中心的前端登录页面,需要对认证中心的前端(nginx)设置允许跨域访问。

server {
	listen          80;
	server_name     oauth.com;

	location /auth/ {
		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://localhost:8080/auth/;
	}
	
	location ^~ /authPage {
		try_files $uri $uri/ /authPage/index.html;
        # 设置允许跨域访问,即客户端的前端ajax请求回调处理时,可以使用window.location.href访问认证中心的前端登录页面
        # 这种情况是认证中心在判断未登录时直接重定向到认证中心的前端登录页面
		add_header 'Access-Control-Allow-Origin' $http_origin;
		add_header 'Access-Control-Allow-Credentials' 'true';
	}
}

1)登录请求处理

前端使用的ajax框架是axios。登录成功重定向到授权服务。

postRequest('/auth/login', this.loginForm).then(resp => {
  if (resp.data.code === 0) {
	var pageUrl = window.location.href
	var param = pageUrl.split('?')[1]
	window.location.href = '/auth/oauth/authorize?'+param
  } else {
	console.log('登录失败:'+resp.data.msg)
  }
})

6、客户端前端配置

前端使用的ajax框架是axios。

1)请求客户端服务器受保护的资源

请求受保护的资源/client1/test

getRequest('/client1/test').then(resp=>{
	// 如果认证中心直接返回页面信息(认证中心的登录页面),则直接进行重定向(建议使用这种)
	if(resp.headers['content-type']=="text/html" && resp.request.responseURL){
	  window.location.href = resp.request.responseURL;
	}
	if (resp.data.code === 0) {
	  this.msg = resp.data.data
	  // 如果认证中心返回了json,且返回码为800表示未登录
	}else if (resp.data.code === 800) {
	  window.location.href = resp.data.data
	} else {
	  console.log('失败:'+resp.data)
	}
})

2)代理nginx配置

server {
	listen          80;
	server_name     client1.com;

	location /client1/ {
        # 设置代理后的Host仍然为请求的域名
		proxy_set_header Host $host;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_pass http://localhost:8081/client1/;
	}
	
	location ^~ /client1Page {
        # 尝试查找uri地址所表示的文件目录,如果没找到,则返回文件/client1Page/index.html
		try_files $uri $uri/ /client1Page/index.html;
	}
}

二、理解http协议响应码302

302重定向是暂时的重定向,搜索引擎会抓取新的内容而保存旧的网址。

通常与location一起使用,搜索引擎根据location所指向的地址,临时重定向到该地址,但不会覆盖旧的网址,此时新网址的返回结果可以在旧网址发起请求的地方获取到,如ajax的返回处理。如果中间会有多次302,则会将最后一次拿到的结果返回到旧网址发起请求的地方,即ajax可以接收到多次重定向后返回的最终结果(最终结果就是最后一次返回非302)后,进行进一步的处理,如后端通过response.sendRedirect(默认的http返回码是200),设置重定向地址是登录页面,则可以使用window.location.href进行重定向。

见客户端的前端处理逻辑:

// 如果认证中心直接返回页面信息(认证中心的登录页面),则直接进行重定向(建议使用这种)
if(resp.headers['content-type']=="text/html" && resp.request.responseURL){
	window.location.href = resp.request.responseURL;
}

三、跨域请求的处理

认证中心后端服务,可以配置支持跨域请求的过滤器CorsFilter,或者在代理服务器nginx中进行配置,只允许配置一次。

认证中心前端服务器nginx,如果是由客户端的前端ajax请求后需要使用window.location.href访问认证中心前端的登录页面,那么认证中心前端服务器nginx需要设置允许跨域访问。

四、ajax遇到重定向问题

通过ajax请求受保护的资源时,浏览器会经过多次302处理,即多次临时重定向后,直到返回非302状态码时,ajax可以获取到结果,如果结果不是json格式,而是html即text/html格式,则此时可以使用window.location.href重定向到返回结果中所指定的url地址。

五、整个登录授权处理过程梳理

三个阶段:

1、ajax请求客户端受保护的资源,直到返回认证中心的登录页面,中间过程会在客户端后端服务和认证中心后端服务之间进行多次302的重定向; 

2、用户输入登录信息并ajax提交给认证中心后台服务,返回响应码200; 

3、ajax处理返回结果,登录成功重新请求认证中心的授权接口,直到返回响应码和客户端的前端主页,中间过程会在客户端后端服务和认证中心后端服务之间进行多次302的重定向。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

springsecurity oauth2实现前后端分离项目的SSO技术点总结 的相关文章

  • c++架构师需要掌握哪些知识

    目录 本文技术梳理主要针对于三类人群的技术需求 c c 43 43 Linux服务器端开发岗位分析 经常被问到的问题 xff1a 技术体系建立的好处 c c 43 43 Linux服务器开发技术学习路径 一 精进基石 二 高性能网络设计 三
  • cmake:使用execute_process调用shell命令或脚本

    CMake可以通过execute process调用shell命令或者脚本 xff0c 其原型如下 xff1a execute process COMMAND lt cmd1 gt args1 COMMAND lt cmd2 gt args
  • 树莓派3B+上安装ubutun mate 18.04.2

    1 准备16G以上储存卡 xff0c 读卡器 2 准备两个软件 xff1a SDCardFormatter Win32DiskImager分别用于储存卡格式化和写入系统文件 链接如下 xff1a 链接 xff1a https pan bai
  • linux应用编程--思维导图

    思维导图软件是xmind 下载源文件点击打开链接
  • 深度学习中Batch、Iteration、Epoch的概念与区别

    在神经网络训练中 xff0c 一般采用小批量梯度下降的方式 Batch Epoch Iteration 就是其中的重要的概念 我们要理解懂得它们都是什么以及它们之间的区别 1 Batch 每次迭代时使用的一批样本就叫做一个Batch xff
  • STM32使用CubeMAX配置的串口中断接收方法

    STM32使用CubeMAX配置的串口中断接收方法 目录 1 定位串口中断发生的地方 2 处理串口中断接收的流程是 xff1a xff08 1 xff09 初始化串口 xff08 2 xff09 在main中第一次调用接收中断函数 xff0
  • SAP 寻找增强点的方法

    SAP中寻找增强的实现方法 SAP 增强已经发展过几代了 xff0c 可参考 SAP 标准教材 BC425 和 BC427 简单的说SAP的用户出口总共有四 代 1 第一代 基于源代码的增强 SAP提供一个空代码的子过程 xff0c 在这个
  • SNMPV3的实现原理

    在snmp发展到V3版本后 xff0c 把snmp的安全性提升到一个新高度 xff0c 这同时也带来了实现上的复杂性 在02年 xff0c 03年我都曾经想进一步的了解它的实现 xff0c 但都没什么进展 这次在实现Csnmp的过程中 xf
  • ubuntu更新错误:dists/artful/main/binary-arm64/Packages 404 Not Found

    Failed to fetch http archive ubuntu com ubuntu dists artful main binary arm64 Packages 404 Not Found IP 91 189 88 162 80
  • 个人公众号开通啦!!!!

    已经开通了个人微信公众号 xff1a 编程时光机 以后会在公众号里和大家分享知识和生吞活 xff0c 欢迎大家关注 xff01 xff01
  • 小白学AI系列(一)-- AI简史

    经过一段时间的酝酿 xff0c 小白学AI系列也正是开始了 xff01 小编将从三个阶段和大家一起入门人工智能 xff0c 掌握常用机器学习算法和数据分析技巧 小编专业为数据融合方向 xff0c 也曾接触过机器学习 xff0c 但由于人工智
  • 小白学AI系列(二) -- Python模块和函数

    原文地址 xff1a 小白学AI系列 xff08 二 xff09 Python模块和函数 今天的内容是带大家学习解释性语言 Python 小编有学过一段时间的C 43 43 和Matlab 相对于二者而言 xff0c Python是作为学习
  • PX4固定翼调试校准流程及实验相关问题记录分析

    pixhawk固定翼调试流程 对于px4固件 xff0c 其对应选择的一般是qgroundcontrol地面站 xff08 APM一般使用Mission Planner xff09 本次调试的固件版本是1 6 5dev xff08 最新的固
  • Ubuntu16.04下PX4环境快速搭建及uORB通信机制

    Ubuntu16 04下的环境搭建 之前搭建PX4环境常常编译不通 xff0c cmake gcc 以及交叉编译器gcc arm none eabi的版本问题导致make固件报错 xff0c 好不容易编译通过了 xff0c 在进行安装jMA
  • PX4固件通过UART连接串口读取超声波,和树莓派3通信

    添加串口读取程序 首先在Firmware msg文件夹下添加rw uart msg span class hljs keyword char span span class hljs number 5 span datastr span c
  • PX4自主飞行相关问题

    调试入坑 赶在回去之前把10月1日新校区试飞相关问题记录一下 首先是调试相关问题 调试具体流程 在校准遥控器时经常出现校准一半就停止的问题 xff0c 期初认为是固件问题 xff0c 换了1 6 5 1 6 3 xff0c 1 5 5三个固
  • PID控制器及其C++实现

    PID控制器原理 PID控制器实际上是对偏差的控制 其原理图如下 其数学的表达如下 u x 61 K p e r r t 43 1 T e r r t d t 43 T D d e r r t d t u x
  • Oracle Systimestamp 函数

    在Oracle PLSQL中 xff0c Systimestamp 函数返回本机数据库上当前系统日期和时间 包括微秒和时区 Systimestamp 函数的语法是 xff1a systimestamp 应用于 xff1a Oracle 9i
  • px4源码解读之fw_att_control

    目录 程序和控制流程源码解读总结 程序和控制流程 个人简单的总结了一下整个程序的流程如下 整个的控制流程图可以在官网中找到 源码解读 在解读源码之前 需要提几个公式 第一个就是协调转弯中的偏航控制 也就是流程图中为什么输入是空速 p 61
  • 安装Mavlink generator出现UnicodeEncodeError错误

    最近在看mavlink 在执行官网的操作时出现了问题 问题如下 span class hljs constant Exception span span class hljs keyword in span span class hljs

随机推荐

  • mc_att_control基础知识:向量运算和罗德里格斯旋转

    向量的叉乘和点乘 在我们的mc att control中有我们的向量的点乘和叉乘 一般遇到的都是三维的运算 S O 3 S O 3 李群 向量点乘 假设向量 a 61 a 1 a 2 a 3
  • 低通滤波器和高通滤波器的程序实现原理推导

    傅立叶变换 拉普拉斯变换和Z变换 对于信号分析而言 傅立叶变换是必不可少的 我们都知道傅立叶变换是把系统从时域变换到频域进行分析 那么拉普拉斯变换和Z变换是干什么的 简单的来说 由于傅里叶变换的收敛有一个狄利克雷条件 xff0c 要求信号绝
  • PX4源码解读之fw_pos_control_l1

    固定翼的位置控制是一个很重要问题 它不同于旋翼的控制 需要对速度和高度进行解耦控制 并且其不能像旋翼那样进行悬停 其转弯的时候有一个转弯半径 本博客不会对源码进行详细的解读 主要是分享一些自己读源码时的资料 自己读的过程中也有注释 想要的同
  • 四元数表示旋转的理解

    哈密尔顿 为了纪念四元数的发明者哈密尔顿 爱尔兰于1943年11月15日发行了下面这张邮票 哈密尔顿简直是个天才 哈密尔顿从小到进入大学之前没有进过学校读书 xff0c 他的教育是靠叔父传授以及自学 他找到了法国数学家克莱罗 xff08 C
  • mc_att_control源码解析

    目录 源码分析内环控制外环控制 之前写了博客分析了一下旋翼姿态控制的基础知识 mc att control基础知识 这次就对照代码将整个旋翼姿态控制过程呈现一遍 先看一下整个程序的框图 从图中可以看到 实际上整个控制分成内外两个环进行控制
  • PX4下载指定版本代码和刷固件的三种方式

    由于之前下载的是1 7版本的代码 现在v5版本的px4需要最新的代码固件 因此这里记录一下 查看自己代码版本 查看自己仓库代码版本的命令如下 git describe always tags 输出 v1 7 0 rc3 9 g0e1c7eb
  • Python怎么调用matlab的

    文章目录 环境的安装安装合适的python环境安装用于 Python 的 MATLAB 引擎 API 环境的安装 安装合适的python环境 研究这个也是在知乎上突然看到的 xff0c 以前python写的多 xff0c 现在由于工作需要
  • insert语句中sequence的使用方法

    我们常常在表中需要插入一些自动增长的值 一方面 我们可以手动添加这些值 xff0c 另一方面 oracle提供的sequence可以帮助我们实现插入的值自动增长 而不需要我们手动的提供值 我们需要做的就是设置好sequence的初值和增长值
  • Ubuntu 安装 vnc server

    查看Ubuntu系统版本 xff1a sudo lsb release a 安装Xfce桌面环境 xff1a sudo apt install xfce4 xfce4 goodies 配置gnome桌面环境 xff0c 参考 xff1a h
  • 嵌入式Linux(4):应用层和内核层数据传输

    文章目录 简介1 如果在应用层使用系统IO对设备节点进行打开 xff0c 关闭 xff0c 读写等操作会发生什么呢 xff1f 写个例子2 假如驱动层的file operations里面没有实现read之类的操作函数 xff0c 会发生什么
  • 嵌入式Linux(5):物理地址到虚拟地址映射

    文章目录 理论知识1 使能了MMU以后有什么好处呢 xff1f 2 MMU非常复杂 xff0c 那么我们如何完成物理地址到虚拟地址的转换呢 xff1f 3 如何查看哪些物理地址被映射过了呢 xff1f 实例 RK3568 理论知识 在Lin
  • 嵌入式Linux(6):驱动模块传参

    文章目录 1 什么是驱动传参 xff1f 2 驱动传参有什么作用 xff1f 3 怎么给我们的驱动传参数 xff1f 传递普通参数传递数组 1 什么是驱动传参 xff1f 驱动传参就是在安装驱动模块 xff08 ko文件 xff09 的时候
  • 嵌入式Linux(7):字符设备驱动--申请设备号

    文章目录 1 字符设备和杂项设备的区别2 注册字符类设备号的两个办法第一种 xff1a 静态分配一个设备号第二种 xff1a 动态分配注销设备号 写代码不带参数测试 xff08 动态分配 xff09 xff1a 带参数测试 xff08 静态
  • 嵌入式Linux(8):字符设备驱动--注册字符类设备

    文章目录 前言上代码 前言 杂项设备 注册杂项设备 xff1a span class token function misc register span span class token punctuation span span clas
  • 嵌入式Linux(9):字符设备驱动--自动创建设备节点

    文章目录 前言1 怎么自动创建一个设备节点 xff1f 2 什么是mdev3 什么是udev 4 怎么自动创建设备节点 xff1f 5 创建和删除类函数 自动生成类代码 6 创建设备函数 自动生成节点代码 前言 在上一节中 xff0c 使用
  • 嵌入式Linux(10):杂项设备和字符设备驱动总结

    文章目录 杂项设备驱动框架图 xff1a 字符设备驱动框架图 xff1a 相对来说 xff0c 如果是操作几个GPIO的操作 xff0c 其实使用简单的杂项设备驱动就可以了 xff0c 字符驱动相对会复杂一点
  • 嵌入式Linux:FrameBuffer 和 DRM/KMS(一)

    文章目录 前言 Linux 的两种显示方案FrameBufferDRM1 GEM2 KMS 参考 xff1a RK3399 探索之旅 Display 子系统 基础概念 参考 xff1a DRM架构介绍 xff08 一 xff09 前言 Li
  • 【RP-RV1126】Ubuntu上配置Buildroot Qt 开发板远程开发调试环境(SSH)

    文章目录 一 前提二 基础设置建设Buildroot编译Qt5配置SSHBuildroot文件系统添加账号密码开发板联网Buildroot文件系统构建时打开rsync功能 三 QtCreator配置3 1 配置Qt交叉编译套件 Kits 配
  • oracle create view语法

    视图实际上是一个或多个表上的预定义查询 xff0c 这些表称为基表 视图并不存储数据 xff0c 只是在查询视图时才访问基表 视图的优点 xff1a 限制用户只能通过视图检索数据 xff0c 对用户屏蔽基表 可以将复杂的查询编写为视图 xf
  • springsecurity oauth2实现前后端分离项目的SSO技术点总结

    参考 xff1a https www jianshu com p b549220e7b34 ivk sa 61 1024320u 一 基于cookie 43 session的SSO基本实现 1 认证中心的授权服务器配置 配置类继承Autho