小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

Spring Security实现用户身份验证及权限管理

# Spring,spring,java,spring boot,spring security 额外说明

收录于:15天前

Spring Security简介

Spring Security是Spring生态系统的成员,为Web应用程序安全提供完整的解决方案。

Spring Security 旨在以一种自包含的方式进行操作,因此你不需要在 Java 运行时环境中放置任何特殊的配置文件。这种设计使部署极为方便,因为可以将目标工件(无论是 JAR还是WAR)从一个系统复制到另一个系统,并且它可以立即工作。

spring Security,一个基于Spring AOP和Servlet过滤器的安全框架。它提供了全面的安全解决方案,在 Web 请求级别和方法调用级别处理身份验证和授权。

Spring sevurity 提供用户身份验证和授权。认证是指用户是否可以访问系统;授权是指用户是否具有执行相关操作的权限。

常见的权限框架的组合
在这里插入图片描述

Spring Security基本使用

Spring Security实际 上是基于Filter实现的,其底层为若干过滤器链。开发者所见到的 Spring Security 提供的功能,都是通过这些过滤器来实现的,这些过滤器按照既定的优先级排列,最终形成一个过滤器链。开发者也可以自定义过滤器,并通过@Order
注解去调整自定义过滤器在过滤器链中的位置。

过滤器不太了解的请移步Servlet和Filter通过两种方式实现认证和访问控制及其基本使用如下:

引入spring security依赖

<!--导入spring security依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

在配置过滤器的登录认证时,一般都配置所有路径,放行登录页面和逻辑,spring security也是,在启动后就会跳转到框架默认的登录界面,用户名是user密码在控制台:

在这里插入图片描述

在这里插入图片描述
登录成功正常访问接口

在这里插入图片描述

实际开发中,需要定制登录页面,需要在数据库中查询用户信息。特殊权限管理需要划分不同的角色。默认的一般不能满足要求,所以必须重写默认配置。只要导入了spring security依赖,接口就会自动受到保护。

用户认证

用户详情服务
spring security提供了接口供开发者使用来定制相关登录时的用户认证逻辑,该接口为UserDetailsService。用户未实现该接口时spring security使用默认的配置即案例的登录效果。

在spring项目中,配置类和配置文件的实现方式基本上有两种,一种是基于注解,一种是基于xml配置文件;在spring boot项目中,还有一种基于实现类的方式,因为spring boot有一个默认的配置,只需要实现覆盖该类的线管对象的方法就可以覆盖默认的。

  1. 配置类更改默认配置

框架默认配置如下
在这里插入图片描述

spring.security.user.name=xiaoxu
spring.security.user.password=xiaoxu

更改默认配置后,控制台没有密码

在这里插入图片描述

在登录页面只有输入配置项才能登录
在这里插入图片描述

  1. 配置类实现,覆盖spring security的默认配置类

在这里插入图片描述

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        auth.inMemoryAuthentication().withUser("xiaoxu").password("xiaoxu").roles("admin");
    }
}

上面的代码也是权限认证的,重写了WebSecurityConfigurerAdapter的默认用户

使用配置文件会修改默认配置参数,但是使用配置类必须覆盖默认配置以及action中使用的其他类,如下,

在这里插入图片描述

重写WebSecurityConfigurerAdapter后,默认的PasswordEncoder并没有实现,所以会报错。

密码编码器

实现加密接口并返回加密对象实例,将其注入到IOC容器中。

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        //密码加密
        BCryptPasswordEncoder passwordEncoder  = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode("123");
        auth.inMemoryAuthentication().withUser("xiaoxu").password(encode).roles("admin");
    }

    //需要注意的是需要实现加密接口并调用,该方法返回一个加密对象
    @Bean
    PasswordEncoder encoder(){
    
        return  new BCryptPasswordEncoder();
    }
}

BCryptPasswordEncoderPasswordEncoder的一个实现类:
在这里插入图片描述

spring启动时,会先查找配置文件,然后查找配置类。如果没有,就会寻找默认配置类的实现类作为启动配置。登录验证也可以通过实现类进行配置。

  1. 自定义实现类,实现永久认证

实现类实现的用户权限认证,包括数据库用户名查询、密码加密、判断等。因此,这里的逻辑也需要重写默认的配置类,因此配置类也需要重写。

//重写配置类使用自定义UserDetailsService覆盖默认值
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    

    //装配自定义的用户登录逻辑
    @Autowired
    UserDetailsService userDetailsService;


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


    //密码加密工具类
    @Bean
    PasswordEncoder encoder(){
    
        return  new BCryptPasswordEncoder();
    }
}
//自定义的角色验证
@Component("userDetailsService")
public class MyUserDetailsSevice implements UserDetailsService {
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
        //设置角色
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User("xiaoxu",new BCryptPasswordEncoder().encode("123"),auths);
    }
}

需要注意的是从外部加载的只有username这一个字符,密码被默认封装起来了。

User对象是框架内置对象。非自定义对象:
在这里插入图片描述

实现了UserDetailsService接口的loadUserByUsername返回值是UserDetails,其源码如下
在这里插入图片描述
包含了用户名,密码等一些信息,返回值User是其一个实现类,其源码如下:
在这里插入图片描述
User又三个参数分别是用户名密码,角色,校色及一个集合且继承自GrantedAuthority这就意味着我们常见该集合必须使用继承类或者其实现类来创建包含角色信息的集合。正如代码所示使用AuthorityUtils.commaSeparatedStringToAuthorityList("role")方法创建的集合。

实现接口的方法应用比较广泛。该方法一般用于实现数据库交互查询用户的账号、密码和角色信息。

下面是对用户验证的修改,使用查询数据的方法:

  • 引入数据库驱动的依赖关系
<!--引入mysql数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.29</version>
</dependency>

<!--spring boot整合myabtis-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
  • 配置数据库驱动信息数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/account?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=root
  • 数据库映射
@Mapper
public interface UserMapper {
    

    @Select("select * from user where user = #{user}")
    List<User> userList(@Param("user") String user);
}

这里的结构化查询语言逻辑是将用户名代入查询用户所有信息。数据库如下:
在这里插入图片描述

  • 自定义安全配置类
//自定义配置类覆盖默认配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    

    //装配自定义的用户登录逻辑
    @Autowired
    UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }
    
    //密码加密工具类
    @Bean
    PasswordEncoder encoder(){
    
        return  new BCryptPasswordEncoder();
    }
}
  • 实现用户认证的接口
@Component("userDetailsService")
public class MyUserDetailsSevice implements UserDetailsService {
    
    
    //mapper层用户数据映射
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
        //代入用户名查询所有信息
        List<com.example.security.pojo.User> users = userMapper.userList(username);

        if(users.size() != 0){
    
            //通过指定方法创建角色参数
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList(users.get(0).getRole());
            //用户信息填入框架的User对象,由框架验证
            return new User(username,new BCryptPasswordEncoder().encode(users.get(0).getPassword()),auths);
        }else {
    
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
            return new User("admin",new BCryptPasswordEncoder().encode("123"),auths);
        }
    }
}

这里的验证逻辑是,如果通过替换用户名可以查到数据,则将正确的用户名和密码提交给框架,框架会进行验证。如果没有查到,则会验证是否是超级管理员账户。

由于该框架只从外部加载了username一个数据,因此这里的查询逻辑是将用户名代入数据库查出用户所有信息,UserDetailsService接口的loadUserByUsername的方法会自动识别设定密码,因此只需要将密码填入到返回的User的参数中即可。

自定义登录页面

spring security框架默认是bootstrsp框架的登录页面。登录成功后,会直接跳转到根路径。这显然是错误的。您需要跳转到主页面或定义的页面。

在这里插入图片描述
在实现的接口下在重写该方法:

//省略实现接口等一些无关代码
@Override
protected void configure(HttpSecurity http) throws Exception {
    
	//省略过滤器代码
    //配置默认登录页面成功跳转页面地址
    http.formLogin().defaultSuccessUrl("/index");
}

配置登录成功的跳转的页面。configure 方法中是一个链式配置,当然也可以不用链式配置,每一个属性配置完毕后再从 http.重新开始写起。

http是一个链式配置。重写这个方法后,需要打开配置开关,比如开启访问权限,否则之前的登录验证会被覆盖。

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    
    http
            //authorizeRequests()方法表示开启权限配置
            .authorizeHttpRequests()
            //.anyRequest().authenticated()表示所有的请求都要认证之后才能访问
            .anyRequest().authenticated()
            .and()
            //配置默认登录页面成功跳转页面地址
            .formLogin().defaultSuccessUrl("/index");

}

在上面代码中先开启过滤器,对所有请求都过滤,未开启就不会跳转到登录页面。配置登录成功后的跳转页面 /指数,这样登录成功后就不会返回根路径。

请添加图片描述

配置登录成功跳转目录的方法由两个defaultSuccessUrl successForwardUrl,它们的区别是前者在访问的是否为参数配置的页面进行跳转。例如,在访问 http://localhost:8080/你好时,defaultSuccessUrl配置额index,那么将会返回到hello,uri的优先级高;successForwardUrl无论地址栏输入的是什么都会返回配置的参数的资源。

有时候需要自定义登录页面,也需要在配置类中进行配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    http
            //authorizeRequests()方法表示开启权限配置
            .authorizeHttpRequests()
            .antMatchers("/static/*")
            //.anyRequest().authenticated()表示所有的请求都要认证之后才能访问
            .permitAll()
            .anyRequest().authenticated()
            .and()
            //配置默认登录页面成功跳转页面地址
            .formLogin()
            .loginPage("/static/login.html")
            .loginProcessingUrl("/login")
            .defaultSuccessUrl("/index");

}

.antMatchers("/static/*")需要放行/static目录,不然返回的页面的uri标识符也会被拦截。.loginPage("/static/login.html")设置返回的页面,覆盖默认配置;.loginProcessingUrl("/login")配置为请求登录的地址。

在这里插入图片描述

  • 配置类覆盖默认跳转页面

SpringSecurityConfig.confifigure(HttpSecurity http)中使用 loginPage("/login/page") 指定前往自定义的登录页面认证请求

实现的配置类有众多的方法,其中confifigure方法是对放行权限和用户管理的,因此接口也主要是实现该方法:

在这里插入图片描述

接口的实现类中可以重写三个方法,但参数不同,方法过滤限制的范围不同,而HttpSecurity的范围更广。这里也重写了这个方法。 AuthenticationManagerBuilder 在登录时对用户进行身份验证。


@Configuration
public class SecurityConfig2 extends WebSecurityConfigurerAdapter {
    

    //装配自定义的用户登录逻辑
    @Autowired
    UserDetailsService userDetailsService;

    //用户认证实现
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
        http
                //authorizeRequests()方法表示开启权限配置
                .authorizeHttpRequests()
                .antMatchers("/static/*")
                //.anyRequest().authenticated()表示所有的请求都要认证之后才能访问
                .permitAll()
                .anyRequest().authenticated()
                .and()
                //配置默认登录页面成功跳转页面地址
                .formLogin()
                .loginPage("/static/login.html")
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/index");

    }
    //密码加密工具类
    @Bean
    PasswordEncoder encoder(){
    
        return  new BCryptPasswordEncoder();
    }
}

该类重写了多个configure会使第一个失效,造成无法登录。
在这里插入图片描述

需要注意的是表单传递的参数必须是usernamepassword,不然就会登陆失败:

<form action="/index" method="get">
    Username: <input type="text" name="username"><br>
    Password: <input type="password" name="password"><br>
    <button type="submit">提交</button>
</form>

我这里一直无法登录,报302错误,如下:

在这里插入图片描述
这是由于过滤器链的放行配置错误造成的,代码时配的过滤器所有请求,登录表单未实现状态记录,需要使用框架代理认证,记录会话状态,不然会出现登录页面的循环。配置如下:

HttpSecurity.loginProcessingUrl("/doLogin")
    <form action="/doLogin" method="post" class="form">
        Username: <input type="text" name="username"><br>
        Password: <input type="password" name="password"><br>
        <button type="submit">提交</button>
    </form>

/doLogin可以定义为任意地址,更多细节移步Spring Security配置访问权限在登录页面循环并报错302

总结

  1. Spring Security 定义了WebSecurityConfigurerAdapter抽象类供用户自定义过滤器规则。

  2. Spring Security 中定义了 UserDetails 接口来规范开发者自定义的用户对象,其一般实现类为UserDetailsService,用户身份验证。

  3. 使用PasswordEncoder接口加密密码。

  4. 过滤规则的配置。

WebSecurityConfigurerAdapter抽象类的抽象方法configure(HttpSecurity http)可以自定义过滤规则。更多细节移步https://www.jianshu.com/c/cba5438e553e感谢作者!@怪诞140819

  1. 数据库认证、用户信息认证。
  2. 注册功能要与PasswordEncoder的加密方式一致。

最后一步是获取会话信息。例如登录后要显示XXX登录系统,则需要从session中获取用户:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

SecurityContextHolder对象获取上下文连接SecurityContextHolder.getContext(),上下文连接获取认证信息SecurityContextHolder.getContext().getAuthentication()。最后再从认证信息获取用户信息即可。

可以通过配置来管理会话

在这里插入图片描述

会话生命周期

在这里插入图片描述

在这里插入图片描述

消除会话
在这里插入图片描述

明确会议所需的工作:

  • HttpSession 无效
  • 清楚SecurityContextHolder
  • 消除会话跳转登录页面


退出消除会话也不需要开发者来完成,均有框架来完成,就行登录时创建会话一样,只需要配置一个代理的接口即可,控制器也不需要实现该接口。如下:

在这里插入图片描述

在这里插入图片描述

@RequestMapping("/main")
public String getMain(){
    
    return "static/index.html";
}

请添加图片描述

WebMvcConfigurer采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制,相当于web.xml。早期版本使用WebMvcConfigurerAdapter。SpringBoot 2.0 后,该类被标记为@Deprecated(弃用)。官方推荐直接实现WebMvcConfigurer或者直接继承WebMvcConfigurationSupport

权限认证

在这里插入图片描述

在这里插入图片描述

用户的角色管理不同的权限,不同角色看到的页面不同,能够访问的资源也不同,spring security为开发者提供了完整的框架供用户使用。其中主要包括Web授权认证方法认证

web授权

通过获取到的角色信息限制用户可以访问的URL,如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    
    http
            .authorizeRequests()
            .antMatchers("/admin/**","/role/**","/user/**").hasAuthority("admin")
            .antMatchers("/role/**","/user/**").hasAuthority("role")
            .antMatchers("/user/**").authenticated()     //配置相应角色必须要有权限访问
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/static/login.html")
            //会话状态代理接口
            .loginProcessingUrl("/doLogin")
// .defaultSuccessUrl("/static/index.html")
            .successForwardUrl("/main")
            .failureUrl("/static/login.html")
            .permitAll()
            .and()
            .csrf().disable()

        //自定义退出配置
            .logout()
            .logoutUrl("/quit")
            .logoutSuccessUrl("/static/login.html");

}

重点是这些配置:

 http
     .authorizeRequests()
     .antMatchers("/admin/**","/role/**","/user/**").hasAuthority("admin")
     .antMatchers("/role/**","/user/**").hasAuthority("role")
     .antMatchers("/user/**").authenticated()     //配置相应角色必须要有权限访问
     .anyRequest().authenticated()

.antMatchers("/role/**","/user/**").hasAuthority("role")所标识的意义是具有role角色的用户可以访问/role,/user地址。.authenticated() 表示需要认证。

数据库表中数据如下:

在这里插入图片描述

UserDetailsService接口的实现类如下:

@Component("userDetailsService")
public class MyUserDetailsSevice implements UserDetailsService {
    

    //mapper层用户数据映射
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    
        //代入用户名查询所有信息
        List<com.example.security.pojo.User> users = userMapper.userList(username);

        if(users.size() != 0){
    
            //通过指定方法创建角色参数
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList(users.get(0).getRole());
            //用户信息填入框架的User对象,由框架验证
            return new User(username,new BCryptPasswordEncoder().encode(users.get(0).getPassword()),auths);
        }else {
    
            List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
            return new User("admin",new BCryptPasswordEncoder().encode("123"),auths);
        }
    }
}

控制器查看用户信息

@RequestMapping("/who")
@ResponseBody
public String getRole(){
    
    //获取认证上下文连接
    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    //获取认证用户名信息
    Object principal = authentication.getPrincipal();
    org.springframework.security.core.userdetails.User user = (org.springframework.security.core.userdetails.User) principal;
    String username = user.getUsername();
    return username;
}

在这里插入图片描述
如GIF所示,role角色的用户只能访问admin以下的权限。

在这里插入图片描述

配置规则的顺序非常重要,首先是特定的或要求更高的权限。。对角色的授权应该在全部资源之前。

方法授权

在spring boot2.0中,除了使用http.authorizeRequests()对web资源授权外还支持服务层方法的安全性支持。通过注解@PreAuthorizePostAuthorize@Secured

@安全

WebSecurityConfigurerAdapter的实现类开启该注解

@EnableGlobalMethodSecurity(securedEnabled = true)

那么在方法中添加这个注解就会限制对该方法的访问,并且注解不同的参数来控制不同的访问权限。 @Secured注解可以指定一个字符串数组参数作为value的值,表示当前用户如果具有这些角色中的任意一个,就可以满足授权条件。

注解不支持表达式,而且需要注意的是这里匹配的字符串需要添加前缀“ROLE_“

IS_AUTHENTICATED_ANONYMOUSLY匿名访问
ROLE_XXX具有XXX权限的允许访问

@Secured("ROLE_ADMIN")
public void addUser(){
    
	//超级用户权限
}

//也可以一次放行多个权限
@Secured({
    "ROLE_ADMIN","ROLE_USER"})
public User  getUserByName(String name){
    
	//...
	return User;
}

总结:

  1. 需要在WebSecuirtyConfig中添加配置
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    

}
  1. 释放方法的权限
@Secured({
    "ROLE_user","ROLE_admin"})

//如下对控制器的配置
@GetMapping("/add")
@Secured("ROLE_admin","ROLE_角色名")
public boolean addUser(){
    
    return true;
}

@预授权

配置类启用该注解

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

为方法添加授权注解

//多个角色授权
@PreAuthorize("hasAnyAuthority('权限名1','权限名2','权限名1')")
//单个角色授权
@PreAuthorize("hasAuthority('权限名')")
@PreAuthorize("hasAnyRole('personal','admin')")

//角色授权
@PreAuthorize("hasRole('ROLE_角色名')")
@PreAuthorize("hasAnyRole('ROLE_角色名','ROLE_角色名')")

该注解支持 Spring EL 表达式

//同时拥有私人和管理员两种权限
@PreAuthorize("hasRole('personal') AND hasRole('admin')") 
@PostAuthorize(" returnObject!=null && returnObject.username == authentication.name")

@PostAuthorize
@PostAuthorize 注解是在方法执行后再进行权限验证,适合验证带有返回值的权限,Spring EL 提供 返回对象能够在表达式语言中获取返回的对象returnObject。

@EnableGlobalMethodSecurity(prePostEnabled=true)的时候,@PostAuthorize可以使用

@GetMapping("/helloUser")
@PostAuthorize(" returnObject!=null && returnObject.username == authentication.name")
public User helloUser() {
    
        Object pricipal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user;
        if("anonymousUser".equals(pricipal)) {
    
            user = null;
        }else {
    
            user = (User) pricipal;
        }
        return user;
}

Spring表达式语言—SpringEL,SpEL是一种强大,简洁的装配Bean的方式,他可以通过运行期间执行的表达式将值装配到我们的属性或构造函数当中也可以调用JDK中提供的静态常量,获取外部Properties文件中的的配置。
SpringEL的使用和EL表达式的使用非常相似,EL表达式在JSP页面更方便的获取后台中的值,而SpringEL就是为了更方便获取Spring容器中的Bean的值.
EL使用${},而SpringEL使用#{}进行表达式的声明。

@RolesAllowed
@RolesAllowed 也是 JSR-250 提供的注解,可以添加在方法上或者类上,当添加在类上时,表示该注解对类中的所有方法生效;如果类上和方法上都有该注解,并且起冲突,则以方法上的注解为准。

另外还有@PreFilter@PostFilter用的比较少。

. . .

相关推荐

额外说明

MyBatis---MyBatis实现Mapper接口方式的mybatis的增,删,改,查

MyBatis实现Mapper接口方式的mybatis的增,删,改,查 1、Mapper接口编程的命名习惯 Mapper接口方式的编程,需要先有一个接口。这个接口的命名一般是xxxxMapper。 比如: User模块的Mapper,接口命名为UserM

额外说明

移动电商——Flutter-屏幕适配方案

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技am

额外说明

新手前端程序员就职指南之 - 入职第一天

新手程序员就职指南之 - 入职第一天 第一篇 - 入职第一天 1. 本篇内容概述: ◇ 了解入职当天的工作内容 ◇ 入职资料的准备 ◇ 配置开发环境 ◇ 公司或者开发账号的申请 ◇ 熟悉公司的环境 2. 正文 Hello, everybody 经过 刻苦

额外说明

Java网络 1.17 CSS3 选择器

CSS3 选择器 兼容性问题 儿子选择器 序选择器 下一个兄弟选择器 兼容性问题 我们现在给大家介绍一下浏览器: windows xp 操作系统安装的 IE6 windows vista 操作系统安装的 IE7 windows 7 操作系统安装的 IE8

额外说明

AIGC实战——生成模型简介

AIGC实战——生成模型简介 0. 前言 1. 生成模型 2. 生成模型与判别模型的区别 2.1 模型对比 2.2 条件生成模型 2.3 生成模型的发展 2.4 生成模型与人工智能 3. 生成模型示例 3.1 简单示例 3.2 生成模型框架 4. 表示学

额外说明

podman容器工具

podman简介 Podman 是 RedHat 开发的一个无守护进程的开源 Linux 原生容器引擎,用于构建、运行和管理 Linux OCI 容器与容器镜像。Podman 于 2018 年初首次发布,原来是 CRI-O 项目的一部分,后来被分离为一个

额外说明

思维和方法:冯诺依曼代码分析法:高效阅读理解和写代码

冯诺依曼代码分析法:高效阅读理解和写代码 数学家冯·诺依曼提出了计算机制造的三个基本原则,即采用二进制逻辑、程序存储执行以及计算机由五个部分组成(运算器、控制器、存储器、输入设备、输出设备),这套理论被称为冯·诺依曼体系结构 冯诺依曼代码分析法,根据

额外说明

PCL学习笔记02:在ROS下建立编译链接PCL模块

文章目录 一、Ubuntu上安装ROS 二、管理ROS环境变量 三、创建ROS工作空间 (一)参考教程 (二)ROS工作空间种类 (三)创建catkin工作空间 (四)测试ROS环境 1、启动ROS核心服务 2、启动海龟节点 3、通过键盘远程控制海龟 (

额外说明

SwinIR实战:如何使用SwinIR和预训练模型实现图片的超分

文章目录 摘要 测试 完整代码: 摘要 论文地址:https://arxiv.org/pdf/2108.10257.pdf 预训练模型下载:https://github.com/JingyunLiang/SwinIR/releases 训练代码下载:ht

额外说明

23个.NET开源项目

Eric Nelson是微软技术的传道者,也是MSDN UK Flash的技术编辑,他编写了一个列表,列出23个UK开发人员推荐的.NET开源项目。微软的一些开源项目如ASP.NET MVC、DLR、IronRuby、IronPython、MEF等则未列

ads via 小工具