SpringSecurity原理剖析及其实战(四)

SpringSecurity原理剖析及其实战(四)

1、认证原理

Spring Security是如何完成身份认证的?

  1. 用户名和密码被过滤器获取到,封装成Authentication,通常情况下是UsernamePasswordAuthenticationToken这个实现类。
  2. AuthenticationManager身份管理器负责验证这个Authentication
  3. 认证成功后,AuthenticationManager身份管理器返回一个被填充满了信息的(包括上面提到的权限信息,身份信息,细节信息,但密码通常会被移除)Authentication实例
  4. SecurityContextHolder安全上下文容器将第3步填充了信息的Authentication,通过 SecurityContextHolder.getContext().setAuthentication(…) 方法中,设置到其中。
public class AuthenticationExample {
    private static AuthenticationManager am = new SampleAuthenticationManager();
    public static void main(String[] args) throws Exception {
        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(result); break;
            } catch (AuthenticationException e) {
                System.out.println("Authentication failed: " + e.getMessage());
} }
        System.out.println("Successfully authenticated. Security context
contains: " +
                SecurityContextHolder.getContext().getAuthentication());
} }
class SampleAuthenticationManager implements AuthenticationManager {
    static final List<GrantedAuthority> AUTHORITIES = new
ArrayList<GrantedAuthority>();
    static {
        AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
    public Authentication authenticate(Authentication auth) throws
AuthenticationException {
// 判断条件,用户名和密码是否相同
if (auth.getName().equals(auth.getCredentials())) {
// 封装认证信息,认证已通过
return new UsernamePasswordAuthenticationToken(auth.getName(),
                    auth.getCredentials(), AUTHORITIES);
        throw new BadCredentialsException("Bad Credentials");
} }

测试
在这里插入图片描述

2、认证流程

在这里插入图片描述

3、相关接口

AuthenticationManager
认证管理器,用于处理一个认证请求,提供了认证方法的入口

public interface AuthenticationManager {
    Authentication authenticate(Authentication authentication)
            throws AuthenticationException;
}

在这里插入图片描述
ProviderManager
ProviderManagerAuthenticationManager 的一个实现类,提供了基本的认证逻辑和方法;它包含 了一个List属性,通过 AuthenticationProvider 接口来扩展出多种认证方式,实际上这是委托者模式的 应用(Delegate)。

委托模式概念

一个对象接收到了请求,但是自己不处理,交给另外的对象处理,就是委托模式,例如 老板接到了活,然后把活转手给了工人去做。

public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication)
            throws AuthenticationException;
    boolean supports(Class<?> authentication);
}

在这里插入图片描述
在Spring Security中,提交的用户名和密码,被封装成UsernamePasswordAuthenticationToken,而 根据用户名加载用户的任务则是交给了UserDetailsService,在DaoAuthenticationProvider中,对应的 方法便是retrieveUser,返回一个UserDetails
在这里插入图片描述
Authentication
Authentication在spring security中是最高级别的身份/认证的抽象,由这个顶级接口,我们可以得到用 户拥有的权限信息列表,密码,用户细节信息,用户身份信息,认证信息。

UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken 实现了 Authentication 主要是将用户输入的用户名和密 码进行封装,并供给AuthenticationManager 进行验证;验证完成以后将返回一个认证成功的Authentication 对象
在这里插入图片描述

public interface Authentication extends Principal, Serializable { //1.权限信息列表,可使用
AuthorityUtils.commaSeparatedStringToAuthorityList("admin,ROLE_ADMIN")返回字符串权 限集合
Collection<? extends GrantedAuthority> getAuthorities(); //2.密码信息,用户输入的密码字符串,在认证过后通常会被移除,用于保障安全。
Object getCredentials();
//3.认证时包含的一些信息,web应用中的实现接口通常为 WebAuthenticationDetails,它记录了
访问者的ip地址和sessionId的值。
Object getDetails(); //4.身份信息,大部分情况下返回的是UserDetails接口的实现类 Object getPrincipal();
//5.是否被认证,认证为true
boolean isAuthenticated();
//6.设置是否能被认证
void setAuthenticated(boolean isAuthenticated) throws
IllegalArgumentException;
}

SecurityContextHolder
用于存储安全上下文(security context)的信息, SecurityContextHolder 默认使用 ThreadLocal 策略来存储认证信息。

// 获取当前用户名
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
    String username = ((UserDetails)principal).getUsername();
} else {
    String username = principal.toString();
}

UserDetailsService

public interface UserDetailsService {
// 根据用户名加载用户信息
UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException;
}

Spring Security内置了两种 UserDetailsManager实现
在这里插入图片描述

实际项目中,我们更多采用调用
AuthenticationManagerBuilder.userDetailsService(userDetailsService) 方法,使用自定义 实现的 UserDetailsService实现类,更加灵活且自由的实现认证的用户信息的读取。

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

UserDetails
用户信息核心接口,默认实现类org.springframework.security.core.userdetails.User
在这里插入图片描述
PasswordEncoder

public interface PasswordEncoder {
/**
* 表示把密码按照特定的解析规则进行解析 */
    String encode(CharSequence rawPassword);
/**
* 表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回
true;如果不匹配, * 则返回 false。第一个参数表示需要被解析的密码。第二个参数表示存储的密 码
*/
    boolean matches(CharSequence rawPassword, String encodedPassword);
}

在这里插入图片描述
BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器

@Test
public void test(){
    String passwd = BCrypt.hashpw("123",BCrypt.gensalt());
    System.out.println(passwd);
    boolean checkpw = BCrypt.checkpw("123", passwd);
    System.out.println(checkpw);
}

SpringSecurity原理剖析及其实战(完结篇)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值