SpringSecurity入门案例——基本功能讲解
简介:本文讲解,SpringSecurity的快速入门案例,主要讲解基本功能,其他拦截器,与jwt的结合在后面的文章中讲解。
项目代码地址:https://gitee.com/geek-li-hua/code-in-blog.git
项目实现
项目准备
导入依赖
这些是这个项目需要的依赖
- Spring Boot Starter JDBC
- Project Lombok
- MySQL Connector/J
- mybatis-plus-boot-starter
- mybatis-plus-generator
- spring-boot-starter-security
<!-- Spring Boot Starter JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- Project Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- MySQL Connector/J --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> <!-- MyBatis Plus Boot Starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <!-- MyBatis Plus Generator --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.3</version> </dependency> <!-- Spring Boot Starter Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
- 完整的pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.15</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>springsecurity-back-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>springsecurity-back-demo</name> <description>springsecurity-back-demo</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot Starter JDBC --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- Project Lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <!-- MySQL Connector/J --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> <!-- MyBatis Plus Boot Starter --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency> <!-- MyBatis Plus Generator --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.3</version> </dependency> <!-- Spring Boot Starter Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- JJWT API --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <!-- JJWT Implementation --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <!-- JJWT Jackson --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置文件
spring.port = 8080 spring.datasource.username=root spring.datasource.password=123456 spring.datasource.url=jdbc:mysql://localhost:3306/db?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
springsecurity登录
当我们启动项目的时候,会出现一个密码,这是因为加入了springsecurity的依赖导致的。
当我们通过一个网页,访问其中一个端口时
会发现需要输入账号和密码,其中账号是user,密码是上面生成的,只有登录之后,我们才可以进行相关的调试。
实现加密
- 我们需要使用到一个类
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
- 我们在测试类中演示它的使用
对密码进行加密
@Test void contextLoads() { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); System.out.println(passwordEncoder.encode("123456")); }
对于同一字符串,每次加密的结果可能也不一样。
- 可以通过matchs方法检验,加密之后与之前是否匹配
可以通过结果看出来的是,虽然对于同一密码每次的加密都不一样,但是,都是可以匹配的。
@Test void contextLoads() { BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); System.out.println(passwordEncoder.encode("123456")); System.out.println(passwordEncoder.matches("123456", "$2a$10$9dBGJIqaejarMaPSJZfzZumyyT4gjY8etzgp3warVCJw2GR6USbtC")); // true System.out.println(passwordEncoder.encode("123456")); System.out.println(passwordEncoder.matches("123456", "$2a$10$WPyb8qBc7DfPSD6l6nVnauiexFQ/MTF6nExLZid4Li5RINhBfr4pC")); // true System.out.println(passwordEncoder.encode("123456")); System.out.println(passwordEncoder.matches("123456", "$2a$10$U0M5Xap/aKo7ZBLiZEvfluZH8FQT10yD2PwInhyU/7W2bSXNoBcba")); // true System.out.println(passwordEncoder.matches("1", "$2a$10$U0M5Xap/aKo7ZBLiZEvfluZH8FQT10yD2PwInhyU/7W2bSXNoBcba")); // false }
让SpringSecurity的登录账号和密码与自己的数据中的用户的信息匹配
- 实现一个UserDetailsServiceImpl类
@Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 根据用户名查询用户信息 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("username", username); User user = userMapper.selectOne(queryWrapper); // 判断用户是否存在 if (user == null) { throw new UsernameNotFoundException("用户名不存在"); } return new UserDetailsImpl(user); } }、
- 再实现一个UserDetailsImpl类,实现UserDetails里面的方法,并且重写,按照我下面的这样
@Data @AllArgsConstructor @NoArgsConstructor public class UserDetailsImpl implements UserDetails { private User user; @Override public Collection<? extends GrantedAuthority> getAuthorities() { // 返回拥有的权限 return null; } @Override public String getPassword() { // 返回密码 return user.getPassword(); } @Override public String getUsername() { // 返回用户名 return user.getUsername(); } @Override public boolean isAccountNonExpired() { // 返回账户是否未过期 return true; } @Override public boolean isAccountNonLocked() { // 返回账户是否未锁定 return true; } @Override public boolean isCredentialsNonExpired() { // 返回凭据是否未过期 return true; } @Override public boolean isEnabled() { // 返回账户是否可用 return true; } }
- 当我们上面都配置正确之后,我们再次运行的时候,就不会生成一个随机密码了
- 配置完上面的之后,我们就可以用数据库里面的账号,进行登录了。
如果数据库里面存的是没有加密的数据,可以加上{noop},这样就可以不用存密文。
两个用户使用123456都可以登录,第二个用户存储的是123456加密之后的密文
- 实现下面的方法,特别是addUser的方法,对用户进行添加,以后注册就是这个原理
@RestController @RequestMapping("/user") public class UserController { @Autowired IUserService userService; /** * 查询所有用户 */ @GetMapping("/all/") public List<User> getAll() { return userService.list(); } /** * 查询单个用户 */ @GetMapping("/{userId}/") public User getUser(@PathVariable int userId) { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("id",userId); return userService.getOne(queryWrapper); } /** * 添加某个用户 直接输入 id name password * @param userId * @param username * @param password * @return Add User Sucessfully */ @GetMapping("/add/{userId}/{username}/{password}/") public String addUser( @PathVariable int userId, @PathVariable String username, @PathVariable String password) { PasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); String encodedPassword = passwordEncoder.encode(password); User user = new User(userId, username, encodedPassword); userService.save(user); return "Add User Successfully"; } /** * 删除某个用户,直接输入 id * @param userId * @return Delete User Successfully */ @GetMapping("/delete/{userId}/") public String deleteUser(@PathVariable int userId) { userService.removeById(userId); return "Delete User Successfully"; } }
如果大家觉得有用的话,可以关注我下面的微信公众号,极客李华,我会在里面更新更多行业资讯,企业面试内容,编程资源,如何写出可以让大厂面试官眼前一亮的简历等内容,让大家更好学习编程,我的抖音,B站也叫极客李华。大家喜欢也可以关注一下