springsecurity默认用户生成

简介: springsecurity默认用户生成

springsecurity默认用户生成

springboot背后默默做了很多事情:

  • 开启springSecurity自动化配置,开启后,会自动创建一个名为SpringSecurityFilterChain的过滤器,并注入到spring容器中,这个过滤器将负责所有的安全管理,包括用户的认证,授权,重定向到登录页面等(springSecurityFilterChain实际上代理了SpringSecurity中的过滤器链)
  • 创建一个UserDetailsService实例,UserDetailsService负责提供用户数据,默认的用户数据是基于内存的用户,用户名为user,密码为随机生成的UUID字符串。
  • 给用户生成一个默认的登录页面。
  • 开启CSRF攻击防御。
  • 开启会话固定攻击防御。
  • 集成X-XSS-Protection
  • 集成X-Frame-Options以防止单击劫持。

默认用户生成

SpringSecurity定义UserDetails接口来规范开发者自定义的用户对象

负责提供用户数据源的接口是UserDetailsService

springSecurity为UserDetailsService提供了默认实现,默认是InMemoryUserDetailsManager

springboot之所以零配置使用SpringSecurity 是因为他提供了很多自动化配置,针对UserDetailsService的自动化配置是UserDetailsServiceAutoConfiguration

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.boot.autoconfigure.security.servlet;

import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.autoconfigure.security.SecurityProperties.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.util.StringUtils;

@Configuration(
   proxyBeanMethods = false
)
@ConditionalOnClass({AuthenticationManager.class})
@ConditionalOnBean({ObjectPostProcessor.class})
@ConditionalOnMissingBean(
   value = {AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class},
   type = {"org.springframework.security.oauth2.jwt.JwtDecoder", "org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector"}
)
public class UserDetailsServiceAutoConfiguration {
   private static final String NOOP_PASSWORD_PREFIX = "{noop}";
   private static final Pattern PASSWORD_ALGORITHM_PATTERN = Pattern.compile("^\\{.+}.*$");
   private static final Log logger = LogFactory.getLog(UserDetailsServiceAutoConfiguration.class);

   public UserDetailsServiceAutoConfiguration() {
   }

   @Bean
   @ConditionalOnMissingBean(
       type = {"org.springframework.security.oauth2.client.registration.ClientRegistrationRepository"}
   )
   @Lazy
   public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties, ObjectProvider<PasswordEncoder> passwordEncoder) {
       User user = properties.getUser();
       List<String> roles = user.getRoles();
       return new InMemoryUserDetailsManager(new UserDetails[]{org.springframework.security.core.userdetails.User.withUsername(user.getName()).password(this.getOrDeducePassword(user, (PasswordEncoder)passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build()});
   }

   private String getOrDeducePassword(User user, PasswordEncoder encoder) {
       String password = user.getPassword();
       if (user.isPasswordGenerated()) {
           logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword()));
       }

       return encoder == null && !PASSWORD_ALGORITHM_PATTERN.matcher(password).matches() ? "{noop}" + password : password;
   }
}

从上述代码中,有两个比较重要的促使系统自动提供一个InMemoryUserDetailsManager的实例:

  1. 当前classpath下存在AuthenticationManager
  2. 当前项目中,系统没有提供AuthenticationManager AuthenticationProvider UserDetailsService ClientRegistrationRepository

满足以上条件,springSecurity会创建InMemoryUserDetailsManager 实例,从方法中可以看到,用户数据源来自SecurityProperties#getUser方法

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.boot.autoconfigure.security;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.DispatcherType;
import org.springframework.util.StringUtils;

@ConfigurationProperties(
    prefix = "spring.security"
)
public class SecurityProperties {
    public static final int BASIC_AUTH_ORDER = 2147483642;
    public static final int IGNORED_ORDER = -2147483648;
    public static final int DEFAULT_FILTER_ORDER = -100;
    private final SecurityProperties.Filter filter = new SecurityProperties.Filter();
    private SecurityProperties.User user = new SecurityProperties.User();

    public SecurityProperties() {
    }

    public SecurityProperties.User getUser() {
        return this.user;
    }

    public SecurityProperties.Filter getFilter() {
        return this.filter;
    }

    public static class User {
        private String name = "user";
        private String password = UUID.randomUUID().toString();
        private List<String> roles = new ArrayList();
        private boolean passwordGenerated = true;

        public User() {
        }

        public String getName() {
            return this.name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return this.password;
        }

        public void setPassword(String password) {
            if (StringUtils.hasLength(password)) {
                this.passwordGenerated = false;
                this.password = password;
            }
        }

        public List<String> getRoles() {
            return this.roles;
        }

        public void setRoles(List<String> roles) {
            this.roles = new ArrayList(roles);
        }

        public boolean isPasswordGenerated() {
            return this.passwordGenerated;
        }
    }

    public static class Filter {
        private int order = -100;
        private Set<DispatcherType> dispatcherTypes;

        public Filter() {
            this.dispatcherTypes = new HashSet(Arrays.asList(DispatcherType.ASYNC, DispatcherType.ERROR, DispatcherType.REQUEST));
        }

        public int getOrder() {
            return this.order;
        }

        public void setOrder(int order) {
            this.order = order;
        }

        public Set<DispatcherType> getDispatcherTypes() {
            return this.dispatcherTypes;
        }

        public void setDispatcherTypes(Set<DispatcherType> dispatcherTypes) {
            this.dispatcherTypes = dispatcherTypes;
        }
    }
}

我们可以看到默认用户为user 默认密码是UUID

默认通过getOrDeducePassword方法中进行二次处理,默认encoder为null ,就在密码加一个{noop}前缀,我们可以通过配置文件添加配置来修改SecurityProperties.User类中的属性

spring.security.user.name=admin
spring.security.user.password=123
spring.security.user.roles=admin,user
相关文章
|
8月前
|
缓存 Java 数据安全/隐私保护
SpringSecurity实现动态管理权限(三)
SpringSecurity实现动态管理权限(三)
176 0
|
2月前
【SpringSecurity 】SpringSecurity 自定义登录页面
【SpringSecurity 】SpringSecurity 自定义登录页面
25 0
|
9月前
|
安全 Java 数据库连接
四.SpringSecurity基础-自定义登录流程
SpringSecurity基础-自定义登录流程
|
8月前
|
JSON 安全 搜索推荐
​SpringSecurity-5-自定义登录验证
​SpringSecurity-5-自定义登录验证
96 0
|
8月前
|
缓存 数据安全/隐私保护
SpringSecurity-11-只允许一个用户登录
SpringSecurity-11-只允许一个用户登录
333 1
SpringSecurity-11-只允许一个用户登录
|
9月前
|
存储 安全 Java
SpringSecurity基础-简单登录实现
1.SpringSecurity介绍 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
67 0
|
9月前
|
存储 安全 Java
二.SpringSecurity基础-简单登录实现
SpringSecurity基础-简单登录实现
|
10月前
|
安全 Java Apache
Springboot整合shiro:实现用户登录和权限验证
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。当然类型大家也可以使用spring security;因为我平时开发的项目都是中小型的,所以使用shiro对于业务来说已经够用了,那么下面是我整理的整合记录;
117 0
|
安全 Java API
原来SpringSecurity整合OAuth2后开放权限拦截路径还能这么玩?
当我们整合了`Spring Security`以及`OAuth2`后发现,有一些业务请求是需要开放的,因为种种原因这时访问者还没有身份标识(`比如:用户刚来,还没有注册,需要进行新用户注册,这时注册业务相关的接口都应该是开放的`),下面我们来看看`ApiBoot`是怎么排除路径不进行权限拦截的。
|
安全 Java 数据安全/隐私保护
Spring Security-自定义登录页面和认证过程其他常用配置
Spring Security-自定义登录页面和认证过程其他常用配置
Spring Security-自定义登录页面和认证过程其他常用配置

热门文章

最新文章