一、环境搭建&相关依赖(无指定版本对应SpringBootVersion)
1.SpringBoot 3.3.1
2.spring-boot-starter-security
3.spring-boot-starter-thymeleaf
4.thymeleaf-extras-springsecurity6
5.spring-boot-starter-web
6.lombok
7.spring-boot-starter-test
8.spring-security-test
9.mysql-connector-java(8.0.30 根据自己)
10.mybatis-plus-boot-starter 3.5.5
11.mybatis-spring 3.0.3
12.maven -3.9.8
程序启动时:
校验用户时:
User对象
户名密码和从内存中获取到的用户信息进行比较,进行用户认证
@Controller
public class IndexController {
@GetMapping("/")
public String index(){
return "index";
}
}
<html xml:th="https://www.thymeleaf.org">
<head>
<title>
Hello Spring Security
</title>
</head>
<body>
<h1>Hello Security</h1>
<a th:href="@{/logout}">Log Out 1 </a>
<a href="/logout">Log Out 2</a>
</body>
</html>
@Configuration //配置类
@EnableWebSecurity //开启springSecurity的自定义配置
public class WebSecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
//创建一个基于内存的用户管理器
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//创建UserDetails对象,用于管理用户名,用户密码,用户角色,用户权限等内容
inMemoryUserDetailsManager.createUser(User.withDefaultPasswordEncoder().username("user").password("123").roles("User").build());
return inMemoryUserDetailsManager;
}
}
环境搭建比较麻烦,自己在数据库中创建一个user表都可以实现案例。建议使用mybatis-x插件快速生成案例环境。
程序启动时:
校验用户时:
@Component
@SuppressWarnings({"all"})
public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {
@Resource
private userMapper userMapper;
@Override
public UserDetails updatePassword(UserDetails user, String newPassword) {
return null;
}
@Override
public void createUser(UserDetails user) {
}
@Override
public void updateUser(UserDetails user) {
}
@Override
public void deleteUser(String username) {
}
@Override
public void changePassword(String oldPassword, String newPassword) {
}
@Override
public boolean userExists(String username) {
return false;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<? extends GrantedAuthority> collection=new ArrayList<>();
//根据用户输入在数据库中查询对应的用户
QueryWrapper<user> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.ge("username", username);
user user = userMapper.selectOne(userQueryWrapper);
if(user==null){
throw new UsernameNotFoundException(username);
}else return new User(
user.getUsername(),
user.getPassword(),
user.getEnabled(),
true, //用户账户是否过期
true,//用户凭证是否过期
true,//用户是否未被锁定
collection); //权限列表
}
}
@RestController
@RequestMapping("/user")
@Slf4j
public class userController {
@Autowired
private userService userService;
@PostMapping("add")
public String saveUser(@RequestBody user user){
log.info(user.toString());//接受到的user对象实例
userService.saveUserDetails(user);
return "添加成功";
}
}
@Service
public class userServiceImpl extends ServiceImpl<userMapper, user>
implements userService{
@Autowired
private DBUserDetailsManager dbUserDetailsManager;
@Override
public void saveUserDetails(user user) {
UserDetails userDetails = User.withDefaultPasswordEncoder().username(user.getUsername()).password(user.getPassword()).build();
dbUserDetailsManager.createUser(userDetails);
}
}
@Override
public void createUser(UserDetails user) {
user user1 = new user();
user1.setUsername(user.getUsername());
user1.setPassword(user.getPassword());
user1.setEnabled(true);
userMapper.insert(user1);
log.info("添加成功");
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//用于开启授权保护
http.authorizeRequests(
authorize->
authorize.anyRequest().//开启所有用户的授权保护
authenticated()) //已认证的请求会被自动授权
.formLogin(Customizer.withDefaults())//自动生成默认的登录页和登出页 使用表单授权方式
.httpBasic(Customizer.withDefaults());//基本授权方式
http.csrf(csrf-> csrf.disable()); //关闭csrf保护策略
return http.build();
}
如果没有指定密码加密算法 默认执行的是BCrypt算法 下图指定使用SHA-1加密。
工厂的静态构造方法把常用的几种密码方案都注入到了缓存Map中,默认注入的 encodingId 对应的是 BCryptPasswordEncoder加密方案,这样系统就可以达到在新存储密码可以使用 BCryptPasswordEncoder 加密方案进行加密,但是对于数据库里面以前用其他方式加密的密码也支持比对。我们可以复写该方法,然后修改这个“encodingId”的值,就可以在几种加密算法中进行切换了。
@SpringBootTest
class SecurityDemoApplicationTests {
public static PasswordEncoder createDelegatingPasswordEncoder() {
String encodingId = "bcrypt";
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put(encodingId, new BCryptPasswordEncoder());
encoders.put("ldap", new org.springframework.security.crypto.password.LdapShaPasswordEncoder());
encoders.put("MD4", new org.springframework.security.crypto.password.Md4PasswordEncoder());
encoders.put("MD5", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("MD5"));
encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
encoders.put("SHA-1", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-1"));
encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
return new DelegatingPasswordEncoder("SHA-1", encoders);
}
@Test
public void test1(){
PasswordEncoder encoder = SecurityDemoApplicationTests.createDelegatingPasswordEncoder();
String result = encoder.encode("zhanghaijie");//即使明文密码相同但是生成的密文也会不同
System.out.println("result = " + result);
}
}
@Controller
public class loginController {
@GetMapping("/login")
public String login() {
return "login"; //跳转访问下方的静态资源
}
}
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>登录</title>
</head>
<body>
<h1>登录</h1>
<div th:if="${param.error}">
错误的用户名和密码.</div>
<!--method必须为"post"-->
<!--th:action="@{/login}" ,
使用动态参数,表单中会自动生成_csrf隐藏字段,用于防止csrf攻击
login: 和登录页面保持一致即可,SpringSecurity自动进行登录认证-->
<form th:action="@{/login}" method="post">
<div>
<!--name必须为"username"-->
<input type="text" name="username" placeholder="用户名"/>
</div>
<div>
<!--name必须为"password"-->
<input type="password" name="password" placeholder="密码"/>
</div>
<input type="submit" value="登录" />
</form>
</body>
</html>
/**
* 此类是Security默认存在的Bean类
*/
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//用于开启授权保护
http.authorizeRequests(
authorize->
authorize.anyRequest().//开启所有用户的授权保护
authenticated()) //已认证的请求会被自动授权
.formLogin(form->{
form.loginPage("/login").permitAll(); //无需授权即可访问当前页面
}) //自定义登录界面
.httpBasic(Customizer.withDefaults());//基本授权方式
http.csrf(csrf-> csrf.disable()); //关闭csrf保护策略
return http.build();
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- gamedaodao.net 版权所有 湘ICP备2024080961号-6
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务