千家信息网

如何理解SpringSecurity原理认证

发表于:2026-11-03 作者:千家信息网编辑
千家信息网最后更新 2026年11月03日,本篇内容主要讲解"如何理解SpringSecurity原理认证",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何理解SpringSecurity原理认证"
千家信息网最后更新 2026年11月03日如何理解SpringSecurity原理认证

本篇内容主要讲解"如何理解SpringSecurity原理认证",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何理解SpringSecurity原理认证"吧!

项目结构基本没有变:

首先我们需要实现UserDetailsService,来获取用户相关的信息封装类UserDetails。

import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;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;@Servicepublic class MyUserDetailService implements UserDetailsService {        @Override        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//              SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("admin");        // 这里可以访问数据库、缓存等获取用户信息,然后构建为User,User是UserDetails的实现类                return User.builder()                                .username("bob")//用户名                //密码 111111 通过BCryptPasswordEncoder加密之后的密文                                .password("$2a$10$344aKAgXr17q7u.8l5i7Cu8wUJr/cxBIniLsVtf/WwFrPx0khY62K")                                .authorities("admin")//权限信息                                .build();        }}

UserDetailsService只做一件事情,就是获取UserDetails,主要是用户名、密码和权限。可以使用Spring Security为我们提供的实现类User,也可以自己实现UserDetails,按自己需求封装。

有了怎样获取UserDetails的方法,我们当然还要通过SecurityConfig配置的AuthenticationManagerBuilder告诉Spring Security。

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import vip.oschool.uinion.security.MyUserDetailService;import javax.annotation.Resource;@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter {        @Resource        MyUserDetailService myUserDetailService;        @Bean        BCryptPasswordEncoder bCryptPasswordEncoder() {                return new BCryptPasswordEncoder();        }        @Override        protected void configure(AuthenticationManagerBuilder auth) throws Exception {                auth.userDetailsService(myUserDetailService);        }}

注意,我们同时还添加了一个BCryptPasswordEncoder,这是一个密码加密器,因为一般情况数据库存放的都是密码的密文,所以,我们还要告诉Spring Security,我们数据库的密码的加密方式是什么,这样Spring Security才能把从客户端接收到的密码使用同样的方式加密,然后做认证。

当然,你也可以通过下面的方式来设置密码加密器:

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {    auth.userDetailsService(myUserDetailService).passwordEncoder(new BCryptPasswordEncoder());}

下面我们把配置文件中的用户名和密码注释掉,重新启动,然后就可以通过我们在UserDetailsService实现中设置的用户bob和密码111111来完成认证。

server:  port: 8081#spring:#    security:#      user:#        name: tim#        password: 111111

Principal

一个比较抽象的概念,用于唯一标识实体的类。

例如,对于用户来说:用户id、手机号、邮箱就可以作为用户的principal来标志用户。

Credentials

简单点理解,就可以看做是密码。

GrantedAuthority

先知道是:角色与权限,具体的后面详细介绍。

UserDetails

用户实体的接口,通过这个接口可以获取:

  • getPassword: 获取密码

  • getUserName: 获取用户名

  • isEnabled: 账户是否可用

  • isAccountNonExpired: 账户是否过期

  • isAccountNonLocked: 账户是否被锁定

  • isCredentialsNonExpired: 密码是否过期

  • getAuthorites:获取用户权限,本质上是用户的角色信息

Spring Security中是:org.springframework.security.core.userdetails.UserDetails

Spring Security提供了一个默认的实现类:org.springframework.security.core.userdetails.User

UserDetailsService

这个接口只有一个目的,就是获取UserDetails,例如,我们需要从数据库获取用户,就需要实现这个接口,并把实现类注入到Spring容器中。

只需要获取UserDetails,认证的工作Spring Security自己获通过用户名和密码来验证,中间可能还涉及一下密码处理的过程。

Authentication

用于存储用户认证详细信息:principal、权限GrantedAuthority等。

自定义的Authentication可以实现Authentication接口,也可以直接继承AbstractAuthenticationToken。

import org.springframework.security.authentication.AbstractAuthenticationToken;import org.springframework.security.core.GrantedAuthority;import java.util.Collection;public class JwtAuthenticationToken extends AbstractAuthenticationToken {    public JwtAuthenticationToken(Collection authorities) {        super(authorities);    }    @Override    public Object getCredentials() {        return null;    }    @Override    public Object getPrincipal() {        return null;    }}

AuthenticationProvider

AuthenticationProvider,顾名思义,认证的提供者,就是用于执行特定类型的身份认证的接口。

我们如果要自定义认证,就需要实现这个接口,例如,现在很多前后端分离项目使用JWT方式来鉴权,那每个请求怎样校验Token呢?

我们就可以创建一个JWTAuthenticationProvider实现AuthenticationProvider,来完成JWT token的认证工作。

import org.springframework.security.authentication.AuthenticationProvider;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;public class JwtAuthenticationProvider implements AuthenticationProvider {    @Override    public Authentication authenticate(Authentication authentication) throws AuthenticationException {        return null;    }    @Override    public boolean supports(Class authentication) {        return authentication.isAssignableFrom(JwtAuthenticationToken.class);    }}

然后可以通过下面的方式把我们自定义的AuthenticationProvider注入。

@EnableWebSecurity()public class SecurityConfig extends WebSecurityConfigurerAdapter {    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.authenticationProvider(daoAuthenticationProvider())                .authenticationProvider(jwtAuthenticationProvider());    }}

前面,我们使用的UserDetailService为什么能生效,是因为做了下面的配置:

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {    auth.userDetailsService(userDetailService);}

认证管理器构建者AuthenticationManagerBuilder的userDetailsService会创建一个DaoAuthenticationProvider,DaoAuthenticationProvider使用DelegatingPasswordEncoder的是一个代理,默认使用的是BCryptPasswordEncoder。

AuthenticationManager与ProviderManager

AuthenticationManager,顾名思义,是用来管理Authentication,其实是管理AuthenticationProvider。

ProviderManager是AuthenticationManager的实现类,它持有一个AuthenticationProvider列表,用来完成不同的认证。

它还持有一个AuthenticationManager的引用,作为其父类。

一般来说我们使用ProviderManager就够了,一般也只需要一个AuthenticationProvider。

如果要配置多个,可以在SecurityConfig(继承了WebSecurityConfigurerAdapter)重写authenticationManager。

 @Overrideprotected AuthenticationManager authenticationManager() {    // ProviderManager可以设置多个AuthenticationProvider    ProviderManager authenticationManager = new ProviderManager(Arrays.asList());    return authenticationManager;}

PasswordEncoder

简单的说就是用于对密码进行加密,存储用户密码的明文绝对不是什么好的习惯,这是对用户的不负责任,也是项目存在风险。

所以,我们一般都会对用户的密码进行加密之后再存储,通常的做法是加盐然后使用sha256再md5之类的算法。

使用Spring Security就需要我们自己实现这些过程了,直接配置PasswordEncoder就可以了。

Spring Security为PasswordEncoder提供了下面一些实现类。

DelegatingPasswordEncoder

即委托密码编码器,兼容多种不同加密方式存储密码。主要用于新旧数据的加密方式的兼容,做到平滑迁移,例如旧数据使用NoOpPasswordEncoder,新数据使用BCryptPasswordEncoder加密。

BCryptPasswordEncoder

基于bcrypt算法的编码器,为了使其更能抵御密码破解,bcrypt故意降低了速度,与其他自适应单向功能一样,应将其调整为大约1秒钟,以验证系统上的密码。BCryptPasswordEncoder的默认实现使用强度10。

Argon2PasswordEncoder

基于 Argon2算法的编码器,Argon2是一种故意慢速的算法,需要大量内存。 与其他自适应单向功能一样,应将其调整为大约1秒钟,以验证系统上的密码。 Argon2PasswordEncoder的当前实现需要BouncyCastle。

Pbkdf2PasswordEncoder

基于 PBKDF2算法的编码器,为了克服密码破解问题,PBKDF2是一种故意缓慢的算法。 与其他自适应单向功能一样,应将其调整为大约1秒钟,以验证系统上的密码。 当需要FIPS认证时,此算法是一个不错的选择。

SCryptPasswordEncoder

基于scrypt算法的编码器, 为了克服自定义硬件scrypt上的密码破解问题,这是一种故意缓慢的算法,需要大量内存。 与其他自适应单向功能一样,应将其调整为大约1秒钟,以验证系统上的密码。

添加测试用户

我们测试的时候,想要添加测试用户,但是又不想太麻烦的去实现UserDetailsService,也可以通过下面的方式:

@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(prePostEnabled = true)public class SecurityConfig extends WebSecurityConfigurerAdapter {        @Override        protected void configure(AuthenticationManagerBuilder auth) throws Exception {                auth.inMemoryAuthentication()                                .withUser("tim")                                .password("111111").roles("admin")                                .and()                                .withUser("allen")                                .password("222222")                                .roles("user");        }}

进入inMemoryAuthentication方法,我们可以看到上面的方式等价于:

@Beanpublic UserDetailsService userDetailsService() {    InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();    manager.createUser(User.withUsername("tim").password("111111").roles("admin").build());    manager.createUser(User.withUsername("allen").password("222222").roles("user").build());    return manager;}

所以,本质上还是相当于创建了一个UserDetailsService,只不过数据保存在内存中。

到此,相信大家对"如何理解SpringSecurity原理认证"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

密码 用户 认证 加密 方式 算法 数据 接口 信息 权限 用户名 编码 编码器 面的 配置 验证 功能 单向 可以通过 就是 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 南京欣网互联网络科技 有格互联网科技 今日互联网科技 互联网金融与金融科技 北京互联网络科技有限公司 天下捷融互联网科技 互联网 科技服务平台 玖二柒互联网科技公司待遇 科技与互联网的利与弊 中化能源互联网科技招聘 全球顶尖互联网科技公司 特约风豹互联网科技为什么扣费 科技赋能视角下互联网保险发展 互联网公司高科技产品 江苏互联网科技小贷 广州燕处互联网科技有限公司 山东大美朱楼互联网科技有限公司 抖集互联网科技技术咨询 科技互联网公司两年变化 互联网对科技影响 云南咖啡 互联网黑科技 互联网科技公司税收优惠 朗新科技与工业互联网 华中科技有哪些互联网大佬 茂名市互联网科技产业园 荆州市昕露互联网络科技有限公司 恒生互联网科技指数跳水 每天都有哪些好的互联网科技 广东工业互联网大赛深圳学泰科技
0