spring security使用和原理简析(2)

转自https://pjmike.github.io/2018/10/12/%E6%B5%85%E6%9E%90Spring-Security-%E6%A0%B8%E5%BF%83%E7%BB%84%E4%BB%B6/

上一篇我们主要讲述了如何搭项目,这里我们就来简单探究一下原理

Spring Security的核心类

Spring Security的核心类主要包括以下几个:

  • SecurityContextHolder: 存放身份信息的容器
  • Authentication: 身份信息的抽象接口
  • AuthenticationManager: 身份认证器,认证的核心接口
  • UserDetailsService: 一般用于从数据库中加载身份信息
  • UserDetails: 相比Authentication,有更详细的身份信息

SecurityContextHolder、Securityontext和Authentication

SecurityContextHolder用于存储安全上下文(security context)的信息,即一个存储身份信息,认证信息等的容器。SecurityContextHolder默认使用 ThreadLocal策略来存储认证信息,即一种与线程绑定的策略,每个线程执行时都可以获取该线程中的 安全上下文(security context),各个线程中的安全上下文互不影响。而且如果说要在请求结束后清除安全上下文中的信息,利用该策略Spring Security也可以轻松搞定。

因为身份信息时与线程绑定的,所以我们可以在程序的任何地方使用静态方法获取用户信息,一个获取当前登录用户的姓名的例子如下:

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}

getAuthentication()方法返回了认证信息,准确的说是一个 Authentication实例,Authentication是 Spring Security 中的一个重要接口,直接继承自 Principal类,该接口表示对用户身份信息的抽象,接口源码如下:

public interface Authentication extends Principal, Serializable {
    //权限信息列表,默认是 GrantedAuthority接口的一些实现
    Collection<? extends GrantedAuthority> getAuthorities();
    //密码信息,用户输入的密码字符串,认证后通常会被移除,用于保证安全
    Object getCredentials();
    //细节信息,web应用中通常的接口为 WebAuthenticationDetails,它记录了访问者的ip地址和sessionId的值
    Object getDetails();
    //身份信息,返回UserDetails的实现类
    Object getPrincipal();
    //认证状态,默认为false,认证成功后为 true
    boolean isAuthenticated();
    //上述身份信息是否经过身份认证
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

AuthenticationManager、ProviderManager 和 AuthenticationProvider

框架用来实现登录的功能

待明确源码

UserDetailsService 和 UserDetails

UserDetailsService简单说就是加载对应的UserDetails的接口(一般从数据库),而UserDetails包含了更详细的用户信息,定义如下:

public interface UserDetails extends Serializable {

   Collection<? extends GrantedAuthority> getAuthorities();

   String getPassword();

   String getUsername();

   boolean isAccountNonExpired();

   boolean isAccountNonLocked();

   boolean isCredentialsNonExpired();

   boolean isEnabled();
}

UserDetails 接口与 Authentication接口相似,它们都有 username、authorities。它们的区别如下:

  • Authentication 的 getCredentials() 与 UserDetails 中的 getPassword() 不一样,前者是用户提交的密码凭证,后者是用户正确的密码,(一般是从数据库中载入的密码),AuthenticationProvider就会对两者进行对比。
  • Authentication 中的 getAuthorities() 实际上是由 UserDetails 的 getAuthorities()传递形成的。
  • Authentication 中的 getUserDetails() 中的 UserDetails 用户详细信息时经过 AuthenticationProvider认证之后填充的。

认证过程的官方样例

public class SpringSecuriryTestDemo {
    private static AuthenticationManager am = new SampleAuthenticationManager();

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        while (true) {
            System.out.println("Please enter your username:");
            String name = in.readLine();
            System.out.println("Please enter your password:");
            String password = in.readLine();
            try {
                Authentication request = new UsernamePasswordAuthenticationToken(name, password);
                Authentication result = am.authenticate(request);
                SecurityContextHolder.getContext().setAuthentication(request);
                break;
            } catch (AuthenticationException e) {
                System.out.println("Authentication failed: " + e.getMessage());
            }
        }
        System.out.println("Successfully authenticated. Security context contains: " + SecurityContextHolder.getContext().getAuthentication());
    }
    static class SampleAuthenticationManager implements AuthenticationManager {
        static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
        static {
            AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
        }
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            if (authentication.getName().equals(authentication.getCredentials())) {
                return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), AUTHORITIES);
            }
            throw new BadCredentialsException("Bad Credentials");
        }
    }
}

结果

Please enter your username:
pjmike
Please enter your password:
123
Authentication failed: Bad Credentials
Please enter your username:
pjmike
Please enter your password:
pjmike
Successfully authenticated.
Security context contains: org.springframew[email protected]441d0230:
Principal: pjmike;
Credentials: [PROTECTED];
Authenticated: true; Details: null;
Granted Authorities: ROLE_USER

了解了简单的认证过程,下一篇在看一下spring security的filter chain

原文地址:https://www.cnblogs.com/jiataoq/p/11073683.html

时间: 2024-08-04 01:42:39

spring security使用和原理简析(2)的相关文章

spring security使用和原理简析(1)

主要参考:https://blog.csdn.net/u012373815/article/details/55225079 源码参考:https://github.com/527515025/springBoot 项目需求 1:实现了用户.角色.权限的动态管理,可以管控到接口地址,已经访问方式(get,post) 2:自定义登录接口 3:结合spring-session,来保存用户登录信息 表结构说明 method来控制相同方法名的不同访问方式(get,post,put等) 项目结构 废话不多

Java Annotation 及几个常用开源项目注解原理简析

PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示例 Override Annotation Java 1 2 3 @Override public void onCreate(Bundle savedInstanceState); Retrofit Annotation Java 1 2 3 @GET("/users/{username}&quo

[转载] Thrift原理简析(JAVA)

转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开发的service需要开放出去的时候,就会遇到跨语言调用的问题,JAVA语言开发了一个UserService用来提供获取用户信息的服务,如果服务消费端有PHP/Python/C++等,我们不可能为所有的语言都适配出相应的调用方式,有时候我们会很无奈的使用Http来作为访问协议;但是如果服务消费端不能

cgroup原理简析:进程调度

本篇来探究下cgroup对cpu的限制机制,前文提到过cgroup也是通过进程调度子系统来达到限制cpu的目的,因此需要了解下进程调度子系统. 因为是介绍cgroup的文章,因此只介绍进程调度中与cgroup密切关联的部分,详细完成的进程调度实现可参考进程调度的相关资料. 本文分为三个部分,首先介绍进程调度中的调度算法,在该基础上引入组调度,最后结合前面文章(cgroup原理简析:vfs文件系统)来说明上层通过echo pid >> tasks, echo n > cpu.shares等

Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义.解析,并对几个 Android 开源库 Annotation 原理进行简析.PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 完整版原文见:Java Android 注解(Ann

SIFT特征原理简析(HELU版)

SIFT(Scale-Invariant Feature Transform)是一种具有尺度不变性和光照不变性的特征描述子,也同时是一套特征提取的理论,首次由D. G. Lowe于2004年以<Distinctive Image Features from Scale-Invariant Keypoints[J]>发表于IJCV中.开源算法库OpenCV中进行了实现.扩展和使用. 本文主要依据原始论文和网络上相关专业分析,对SIFT特征提取的算法流程进行简单分析.由于涉及到的知识概念较多,本人

Spring Security入门(2-2)Spring Security 的运行原理 2

Java配置和表单登录 因此使用Java代码配置Spring Security主要是这两个步骤:1.创建过滤器2.注册过滤器. 1.创建过滤器这段配置创建一个Servlet Filter:springSecurityFilterChain,其负责应用中的所有安全,包括:保护应用的URLS,验证提交的username和password,重定向到登录页面等. 通过以下代码可以看到使用Java配置Spring Security的基础案例: @EnableWebSecuritypublic class

ARP攻击原理简析及防御措施

0x1  简介 网络欺骗攻击作为一种非常专业化的攻击手段,给网络安全管理者,带来严峻的考验.网络安全的战场已经从互联网蔓延到用户内部的网络, 特别是局域网.目前利用ARP欺骗的木马病毒在局域网中广泛传播,导致网络随机掉线甚至整体瘫痪,通讯被窃听,信息被篡改等严重后果. 0x2  ARP协议概述 ARP协议(address resolution protocol)地址解析协议 一台主机和另一台主机通信,要知道目标的IP地址,但是在局域网中传输数据的网卡却不能直接识别IP地址,所以用ARP解析协议将

iOS Block原理简析

Block的语法 Block是iOS闭包的实现方式,能够获取局部变量的匿名函数. Block的OC声明 返回值类型 (^Block变量名字)(参数列表) = (参数列表){}; 例子 int (^add)(int a,int b) = ^(int a, int b) { return a + b; }; int sum = add(1,4); NSLog(@"sum = %d",sum); NSString* (^getFullName)(NSString *first,NSStrin