您的位置:首页 > 文旅 > 美景 > 销售管理软件免费版_香港特别行政区的面积_乌鲁木齐seo_做外贸用什么软件找客户

销售管理软件免费版_香港特别行政区的面积_乌鲁木齐seo_做外贸用什么软件找客户

2024/10/5 19:14:44 来源:https://blog.csdn.net/ldcigame/article/details/142577416  浏览:    关键词:销售管理软件免费版_香港特别行政区的面积_乌鲁木齐seo_做外贸用什么软件找客户
销售管理软件免费版_香港特别行政区的面积_乌鲁木齐seo_做外贸用什么软件找客户

一、认证流程分析

上篇文章当中,我们一步一步查阅源码方式对认证流程有了一些认证,本章节梳理一下整个流程,最后形成一张图,以更直观的方式来理解认证的整个流程.

1.1 认证当中步及的接口和类

1.1.1 【抽象类】AbstractAuthenticationProcessingFilter

  • 实现了GenericFilterBean抽象类,GenericFilterBean实现了接口Filter
  • 此类当中重写了doFilter()方法,当请求到达的时候,要经过该过滤器,并且执行doFitler方法
  • 定义模板方法Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)

1.1.2 【实现类】UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter

  • 核心功能实现父类定义的模板方法

1.1.3 【接口】AuthenticationManager

  • 认证管理器接口
  • 提供了核心认证方法authenticate

1.1.4 【实现类】ProviderManager implements AuthenticationManager

  • 实现了接口当中的定义的抽象方法authenticate

1.1.5 【接口】AuthenticationProvider

  • 认证的提供方法, 可以处理特定 Authentication 实现
  • 提供了认证方法authenticate

1.1.6 【抽象类】AbstractUserDetailsAuthenticationProvider implement AuthenticationProvider

  • 实现了接口AuthenticationProvider定义的authenticate()方法
  • 定义模板方法UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication), 用于检索用户

1.1.7 【实现类】DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider

  • 实现父类定义的模板方法, 完成用户的检索

1.1.8 【接口】UserDetailsService

  • 定义抽象方法:UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
  • 该方法作用: 根据用户名称在数据源当中里查询出具体用户信息, 并且封装为UserDetails对象

1.1.9 【实现类】InMemoryUserDetailsManager implements UserDetailsManager

  • 基于内存的数据存储,实现接口当中定义的方法loadUserByUsername

1.1.10 【接口】 UserDetails

  • 提供用户的核心信息封装
  • 包括用户名称、用户密码、权限列表集合、用户状态信息

1.1.11 【实现类】User implements UserDetails

  • 实现接口相关方法
  • 对认证的用户信息进行封装

1.1.12 【接口】Authentication

  • 定义了认证用户的主体信息
  • 权限信息、认证主体信息、用户凭证

1.1.13 【实现类】UsernamePasswordAuthenticationToken

  • 间接实现了接口Authentication
  • 用来将用户传递的用户名称、密码封装成Authentication对象
  • 存储用户名称的时候也是传入的此对象

1.1.14 【图】 认证图解

以上就是认证和授权当中所使用到的接口、抽象类和实现类.结合上篇文章的认证流程的源码分析,可以得出如下的认证时序图
1

二、默认密码处理流程

2.1 UserDetailsServiceAutoConfiguration自动装配

在上篇文章的认证流程的源码分析当中,从数据源当中获取UserDetails对象的时候,使用的是如下的代码

UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);

this.getUserDetailsService()返回UserDetailsService对象,问题题为什么是返回的InMemoryUserDetailsManager的对象呢?为什么不是其它对象呢?
2

其实在应用程序加载的时候,已经默认将InMemoryUserDetailsManager初始化好了,然后将其放到容器当中了.查看UserDetailsServiceAutoConfiguration源码.

@AutoConfiguration
@ConditionalOnClass(AuthenticationManager.class)
@Conditional(MissingAlternativeOrUserPropertiesConfigured.class)
@ConditionalOnBean(ObjectPostProcessor.class)
@ConditionalOnMissingBean(value = { AuthenticationManager.class, AuthenticationProvider.class, UserDetailsService.class,AuthenticationManagerResolver.class }, type = "org.springframework.security.oauth2.jwt.JwtDecoder")
public class UserDetailsServiceAutoConfiguration {// ....
}

其中核心方法如下所示:

// 将InMemoryUserDetailsManager对象放到容器当中
// InMemoryUserDetailsManager是将数据存储到内存当中.这也是spring security默认的存储策略
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager(SecurityProperties properties,ObjectProvider<PasswordEncoder> passwordEncoder) {SecurityProperties.User user = properties.getUser();List<String> roles = user.getRoles();return new InMemoryUserDetailsManager(User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build());
}

2.2 默认用户名称生成策略

在UserDetailsServiceAutoConfiguration#inMemoryUserDetailsManager自动装配方法当中实例化InMemoryUserDetailsManager的时候, 设置的默认的用户名称和密码.

return new InMemoryUserDetailsManager(User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build());

其中User.withUsername(user.getName())表示设置用户名称
进入User.withUsername方法, 该方法表示设置用户名称

public static UserBuilder withUsername(String username) {return builder().username(username);
}

通过构建者模式,设置用用户名称,进入方法查看
3

public UserBuilder username(String username) {Assert.notNull(username, "username cannot be null");this.username = username;return this;
}

this.name=username,这个赋值语句, 用于将传入的用户名称存储到内存当中.

User.withUsername(user.getName()), user.getName()表示获取用户名称,查看该方法
4

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

直接返回this.name的值, 找到趸同变量name.

private String name = "user";

所以默认的用户名称为: user.

2.3 默认密码生成策略

在UserDetailsServiceAutoConfiguration#inMemoryUserDetailsManager自动装配方法当中实例化InMemoryUserDetailsManager的时候, 设置的默认的用户名称和密码.

return new InMemoryUserDetailsManager(User.withUsername(user.getName()).password(getOrDeducePassword(user, passwordEncoder.getIfAvailable())).roles(StringUtils.toStringArray(roles)).build());

.password(getOrDeducePassword(user, passwordEncoder.getIfAvailable()))将密码存储到从内存当中,调用了UserDetailsServiceAutoConfiguration#getOrDeducePassword方法获取密码

private String getOrDeducePassword(SecurityProperties.User user, PasswordEncoder encoder) {String password = user.getPassword();if (user.isPasswordGenerated()) {user.getPassword()));}if (encoder != null || PASSWORD_ALGORITHM_PATTERN.matcher(password).matches()) {return password;}return NOOP_PASSWORD_PREFIX + password;
}

user.getPassword()表示获取密码
6

public String getPassword() {return this.password;
}
private String password = UUID.randomUUID().toString();

默认采用的是uuid的方式生成的密码,最后将生成的用户名称和密码存储到内存当中.

三、自定义认证页面、用户名称和密码

3.1 自定义认证页面

在项目当中的resources/static目录下创建一个html文件,起名字: login.html即可.
5

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>登录</title>
</head>
<body><form method="post" action="/login">用户名称: <input type="text" name="username"><br>用户密码: <input type="password" name="password"><br><input type="submit" value="登录"></input></br></input></br></input></form>
</body>
</html>

特别注意: 这里只是替换了认证的登录页面,具体的认证流程处理还是由spring security默认的流程去处理即可.
怎么才能让spring security使用我们自己定义的认证页面呢? 在上篇文章的认证流程的源码分析当中,提到了spring security的自动装配, 如果想让自动装配失效,则必须要破坏自动装配的生效条件.

class DefaultWebSecurityCondition extends AllNestedConditions {DefaultWebSecurityCondition() {super(ConfigurationPhase.REGISTER_BEAN);}@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })static class Classes {}@ConditionalOnMissingBean({ SecurityFilterChain.class })static class Beans {}
}

@ConditionalOnMissingBean({ SecurityFilterChain.class }), 如果在容器当中,没有 SecurityFilterChain.class 这个bean对象,则默认配置生效,相反的说,如果我们自己定义了 SecurityFilterChain.class 对象,将它添加到容器当中,则默认配置失效,会执行我们自己的认证配置.

3.2 编写配置文件

@Configuration
public class SpringSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {returnhttp.authorizeHttpRequests(authorize -> {// 如果请求的是/login.html则放行authorize.requestMatchers("/login.html").permitAll().anyRequest().authenticated(); // 其它的请求都需要认证}).formLogin(form -> { // 配置登录相关的信息// 用来指定默认的登录页面, 注意: 一旦自定义登录页面以后必须配置一下登录的url【必须】form.loginPage("/login.html").loginProcessingUrl("/login"); // ①. 指定处理登录的url【必须的】}).csrf(AbstractHttpConfigurer::disable).build();}
}

重点内容都添加到注释当中了,注意查看.
配置完成之后,启动项目,请求接口发现换成我们自己定义的登录页面了.
7
输入默认的用户名称及密码,成功访问接口
6

3.3 自定义密码

在spring security自动装配当中

@AutoConfiguration(before = UserDetailsServiceAutoConfiguration.class)
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {@Bean@ConditionalOnMissingBean(AuthenticationEventPublisher.class)public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {return new DefaultAuthenticationEventPublisher(publisher);}
}

@EnableConfigurationProperties(SecurityProperties.class), 关于spring security的所有属性配置被引入了,我们查看一下SecurityProperties类当中,可以看到
9
在application.yml文件当中配置密码:

spring:security:user:name: byejackpassword: byejack

再次启动项目,访问接口
观察启动的控制台日志输出,可以发现,如果我们自己定义了密码,则spring security不再生成密码.
清除浏览器缓存之后,再次访问/hello接口
7
访问成功.
8

这里需要注意的是, 当认证成功一次,默认的spring security会将用户凭证保存到session当中,此时清除一下浏览器缓存,或者直接在浏览器当中,删除凭证,再次测试即可. 或者直接在配置文件当中关闭也可.
10

三、总结

3.1 内容总结

  • 认证、授权当中所用到的类或者接口
  • 认证流程图解
  • 默认的密码生成策略
  • 自定义认证登录页面、密码

3.2 下篇内容

  • 自定义认证页面细节
  • 自定义存储用户信息的数据源

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com