SpringSecurity 核心组件

简介: 在SpringSecurity中的jar分为4个

@[TOC]

SpringSecurity 结构

在SpringSecurity中的jar分为4个,作用分别为

jar 作用
spring-security-core SpringSecurity的核心jar包,认证和授权的核心代码都在这里面
spring-security-config 如果使用Spring Security XML名称空间进行配置或Spring Security的
Java configuration支持,则需要它
spring-security-web 用于Spring Security web身份验证服务和基于url的访问控制
spring-security-test 测试单元

组件:SecurityContextHolder

在spring-security-core中的SecurityContextHolder,是一个非常基础的对象,存储了当前应用的上下文SecurityContext,而在SecurityContext可以获取Authentication对象。也就是当前认证的相关信息会存储在Authentication对象中。

image.png

默认情况下,SecurityContextHolder是通过 ThreadLocal来存储对应的信息的。也就是在一个线程中我们可以通过这种方式来获取当前登录的用户的相关信息。而在SecurityContext中就只提供了对Authentication对象操作的方法

public interface SecurityContext extends Serializable {

    Authentication getAuthentication();

    void setAuthentication(Authentication authentication);

}

xxxStrategy的各种实现

image.png

策略实现 说明
GlobalSecurityContextHolderStrategy 把SecurityContext存储为static变量
InheritableThreadLocalSecurityContextStrategy 把SecurityContext存储在InheritableThreadLocal中
InheritableThreadLocal解决父线程生成的变量传递到子线程中进行使用
ThreadLocalSecurityContextStrategy 把SecurityContext存储在ThreadLocal中

组件:Authentication

Authentication是一个认证对象。在Authentication接口中声明了如下的相关方法。

public interface Authentication extends Principal, Serializable {

    // 获取认证用户拥有的对应的权限
    Collection<? extends GrantedAuthority> getAuthorities();

    // 获取哦凭证
    Object getCredentials();

    // 存储有关身份验证请求的其他详细信息。这些可能是 IP地址、证书编号等
    Object getDetails();

     // 获取用户信息 通常是 UserDetails 对象
    Object getPrincipal();

    // 是否认证
    boolean isAuthenticated();

    // 设置认证状态
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;

}

image.png

基于上面讲解的三者的关系,在项目中如下来获取当前登录的用户信息了。

    public String hello(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication.getPrincipal();
        if(principal instanceof UserDetails){
            UserDetails userDetails = (UserDetails) principal;
            System.out.println(userDetails.getUsername());
            return "当前登录的账号是:" + userDetails.getUsername();
        }
        return "当前登录的账号-->" + principal.toString();
    }

调用 getContext()返回的对象是 SecurityContext接口的一个实例,这个对象就是保存在线程中的。接下来将看到,Spring Security中的认证大都返回一个 UserDetails的实例作为principa。

组件:UserDetailsService

在上面的关系中可以看到在Authentication中存储当前登录用户的是Principal对象,而通常情况下Principal对象可以转换为UserDetails对象。UserDetails是Spring Security中的一个核心接口。它表示一个principal,但是是可扩展的、特定于应用的。可以认为 UserDetails是数据库中用户表记录和Spring Security在 SecurityContextHolder中所必须信息的适配器。

public interface UserDetails extends Serializable {

    // 对应的权限
    Collection<? extends GrantedAuthority> getAuthorities();

    // 密码
    String getPassword();

    // 账号
    String getUsername();

    // 账号是否过期
    boolean isAccountNonExpired();

    // 是否锁定
    boolean isAccountNonLocked();

    // 凭证是否过期
    boolean isCredentialsNonExpired();

    // 账号是否可用
    boolean isEnabled();

}

而这个接口的默认实现就是 User

image.png

那么这个UserDetails对象什么时候提供呢?在[上文介绍的数据库认证]的Service中我们就用到了,有一个特殊接口 UserDetailsService,在这个接口中定义了一个loadUserByUsername的方法,接收一个用户名,来实现根据账号的查询操作,返回的是一个 UserDetails对象。

public interface UserDetailsService {

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

}

UserDetailsService接口的实现有如下:

image.png

Spring Security提供了许多 UserDetailsSerivice接口的实现,包括使用内存中map的实现(InMemoryDaoImpl 低版本 InMemoryUserDetailsManager)和使用JDBC的实现(JdbcDaoImpl)。但在实际开发中我们更喜欢自己来编写,比如UserServiceImpl我们的案例


/**
 * UserService接口的实现类
 */
@Service
public class UserServiceImpl extends UserDetailsService {

    @Autowired
    UserMapper userMapper;

    /**
     * 根据账号密码验证的方法
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userMapper.queryByUserName(username);
        System.out.println("---------->"+user);
        if(user != null){
            // 账号对应的权限
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            // 说明账号存在 {noop} 非加密的使用
            UserDetails details = new User(user.getUserName()
                    ,user.getPassword()
                    ,true
                    ,true
                    ,true
                    ,true
                    ,authorities);
            return details;
        }
        throw new UsernameNotFoundException("账号不存在...");

    }
}

组件:GrantedAuthority

在Authentication中看到不光关联了Principal还提供了一个getAuthorities()方法来获取对应的GrantedAuthority对象数组。

public interface GrantedAuthority extends Serializable {


    String getAuthority();

}

组件总结

核心对象 作用
SecurityContextHolder 用于获取SecurityContext
SecurityContext 存放了Authentication和特定于请求的安全信息
Authentication 特定于Spring Security的principal
GrantedAuthority 对某个principal的应用范围内的授权许可
UserDetail 提供从应用程序的DAO或其他安全数据源构建Authentication对象所需的信息
UserDetailsService 接受String类型的用户名,创建并返回UserDetail
相关文章
|
3月前
|
存储 安全 Java
Spring Security与OAuth2集成开发
Spring Security与OAuth2集成开发
|
4月前
|
前端开发 Java Spring
10个SpringMVC的核心组件详解
Spring MVC 核心组件包括 DispatcherServlet(前端控制器)、Controller(处理请求)、HandlerMapping(映射请求到方法)、HandlerAdapter(调用不同处理器)、ViewResolver(解析视图)、ModelAndView(传递数据到视图)、数据绑定、异常处理器、消息转换器和主题解析器。这些组件协同工作,支持基于 MVC 的 Web 应用开发,使请求处理、业务逻辑和视图渲染得以有序进行。了解并掌握这些组件有助于深入理解 Spring MVC 的工作原理。【5月更文挑战第2天】
150 4
|
4月前
|
存储 安全 Java
20个SpringSecurity框架核心组件源码详解
以上是 V 哥给大家整理的20个Spring Security 中核心组件的分析与运行过程,理解后可助你玩转Spring Security,如果文章对你有帮助,客官请点赞收藏转发给更多需要的兄弟,任何疑问请评论区与V哥交流。
|
4月前
|
前端开发 Java Spring
使用Spring Boot集成Shiro时出现了无法注入Service的问题
使用Spring Boot集成Shiro时出现了无法注入Service的问题
|
4月前
|
安全 Java Spring
springboot整合spring security 安全认证框架
springboot整合spring security 安全认证框架
SpringSecurity框架
SpringSecurity框架
22 0
|
安全 JavaScript 小程序
Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
Spring Cloud实战 | 第九篇:Spring Cloud整合Spring Security OAuth2认证服务器统一认证自定义异常处理
|
存储 缓存 安全
Spring Security系列教程11--Spring Security核心API讲解
前言 经过前面几个章节的学习,一一哥 带大家实现了基于内存和数据库模型的认证与授权,尤其是基于自定义的数据库模型更是可以帮助我们进行灵活开发。但是前面章节的内容,属于让我们达到了 "会用" 的层级,但是 "为什么这么用",很多小伙伴就会一脸懵逼了。对于技术学习来说,我们追求的不仅要 "知其然",更要 "知其所以然"! 本篇文章中,壹哥 就跟各位小伙伴一起来了解剖析Spring Security源码内部,实现认证授权的具体过程及底层原理。接下来请各位做好心理准备,以下的学习过程可能会让你心理 “稍有不适” 哦,因为每次看源码都懵懵的...... 一. Spring Security认证请求完整
377 0
|
安全 Java 数据库
Spring Security系列教程23--Spring Security的四种权限控制方式
前言 在前面的章节中,一一哥 已经给大家介绍了Spring Security的很多功能,在这些众多功能中,我们知道其核心功能其实就是 认证+授权。在前面我们分别基于内存模型、基于默认的数据库模型、基于自定义数据库模型实现了认证和授权功能,但是不管哪种方式,我们对某个接口的拦截限制,都是通过编写一个SecurityConfig配置类,在该类的configure(HttpSecurity http)方法中,通过http.authorizeRequests().antMatchers("/admin/**")...这样的代码进行的权限控制。 这种权限控制方法虽然也可以实现对某些接口的拦截或放行,但
1649 0