一、SpringSecurity认证
1. 在配置文件中定义用户
如果自定义了账号和密码,则springsecurity就不在提高账号和密码了。
2. 自定义多个账号和密码
上面那种方式只能自定义一个账号和密码, 如何定义多个账号和密码呢。
指定的账号和密码必须指定密码加密器。如果不使用密码加密器可以:
我们在配置类中定义多个账号和密码后,配置文件中的账号和密码也会失效。
3. 密码加密器
常用的密码加密器为:BCryptPasswordEncoder ,官方也推荐这种密码加密器。
因为BCryptPasswordEncoder实现了PasswordEncoder接口,所以它有两个关键的方法:encode和matches
- encode 传入明文密码,返回加密后的密码
- matches 传入明文密码和加密后的密码,返回一个Boolean值,如果密码匹配成功返回true。
public static void main(String[] args) {
// PasswordEncoder 里面提供了两个方法:
// 1. String encode(CharSequence rawPassword);对你的原始密码进行加密
// 2. boolean matches(CharSequence rawPassword, String encodedPassword); 输入的密码和加密后的密码进行匹配。
BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
String encode = passwordEncoder.encode("123456");
System.out.println(encode);
String encode1 = passwordEncoder.encode("123456");
System.out.println(encode1);
String encode2 = passwordEncoder.encode("123456");
System.out.println(encode2);
/*
$2a$10$k8XcVVIyNaXOfYR/q5v1veda/koy21JJ6FfGYQeRcubjuv1qax/v6
$2a$10$bpRCTSDeethXZB54Bsx8IePYD3cFBUnIuKyBDmT8KrJBdHj0zPdsG
$2a$10$Xie5.5c74ULT3Bm.laYOfeMCpeUoKbxbOKD57cCFhaBnoxuZv/G5.
我们发现对同一个密码进行加密后得到的结果不一样。---为了安全。
*/
boolean matches1 = passwordEncoder.matches("123456", "$2a$10$k8XcVVIyNaXOfYR/q5v1veda/koy21JJ6FfGYQeRcubjuv1qax/v6");
boolean matches2 = passwordEncoder.matches("123456", "$2a$10$bpRCTSDeethXZB54Bsx8IePYD3cFBUnIuKyBDmT8KrJBdHj0zPdsG");
boolean matches3 = passwordEncoder.matches("123456", "$2a$10$Xie5.5c74ULT3Bm.laYOfeMCpeUoKbxbOKD57cCFhaBnoxuZv/G5.");
System.out.println(matches1);
System.out.println(matches2);
System.out.println(matches3);
//不管密码加密后,结果为什么,但是只要使用的同一个密码加密器,他们在对象密码比对时,都会返回相同结果(true)
}
使用密码加密器修改配置类
在配置文件中定义一下BCryptPasswordEncoder
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
不要在一个类中定义bean并使用bean
package com.ykq.springsecurity03.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
/**
* @program: springsecurity03
* @description:
* @author: 闫克起2
* @create: 2022-10-29 15:28
**/
//使用该注解表示该类为配置类
@Configuration
public class MySpringSecurityConfig {
@Autowired
private PasswordEncoder passwordEncoder;
@Bean //返回的对象交于spring容器来管理该对象
public UserDetailsService userDetailsService(){
//我们先基于内存创建多个账号和密码----后期我们使用数据库中的账号和密码
InMemoryUserDetailsManager inMemoryUserDetailsManager=new InMemoryUserDetailsManager();
inMemoryUserDetailsManager.createUser(
//用户的账号
User.withUsername("admin")
//用户的密码
.password(passwordEncoder.encode("123456"))
//该用户具有的角色--必须分配
.roles("admin")
.build()
);
inMemoryUserDetailsManager.createUser(
//用户的账号
User.withUsername("user")
//用户的密码
.password(passwordEncoder.encode("123456"))
//该用户具有的角色
.roles("user")
.build()
);
return inMemoryUserDetailsManager;
}
}
4. 自定义登录页面
认证过程现在是定义SecurityFilterChain 的Bean来完成认证过程,目前要是登录的话要先关闭csrf,才能登录
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.formLogin()
//默认登录页面
.loginPage("/login.html")
//登录的处理路径,无需自己创建该路径的业务处理功能。
.loginProcessingUrl("/login")
//通过这两个可以修改表单中name的值
/*.usernameParameter("user")
.passwordParameter("pwd")*/
//放行
.permitAll()
//其他的请求都需要认证
.and()
.authorizeRequests().anyRequest().authenticated()
//禁用跨域请求伪造 csrf
.and()
.csrf().disable()
.build();
}
<form action="/login" method="post">
<!--用户名默认情况为username-->
用户名:<input type="text" name="username"><br/>
<!--密码默认为password-->
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
表单一定要设置post方式提交!action提交的地址要与loginProcessingUrl提供的地址一致,(两边可以都不写,有默认请求路径,默认好像是请求login,如果写了都要写)