文章目录
在Spring Boot应用中集成Spring Security实现用户注册和登录
前言
本文描述了在Spring Boot应用中如何集成Spring Security实现用户注册和登录。
环境和工具:
- Spring Boot 2.4 (对应Spring为Spring 5)
- Thymeleaf
- Spring Security
- Spring Data JPA
- MySQL 8.0
引入依赖
引入Spring Security依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
引入Spring Data JPA和MySQL依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
引入Thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
说明:
thymeleaf-extras-springsecurity5
为Thymeleaf对应Spring 5的security的依赖。
引入前端依赖
因为采用的时Thymeleaf,不是前后端分离架构,因此需要额外引入前端依赖,或者需要将前端所需要的静态文件放到相应目录或从CDN获取。
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.2.1</version>
</dependency>
引入其他依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.3</version>
</dependency>
表设计
创建以下表:
t_sys_user
- 用户信息表t_sys_role
- 角色信息表t_sys_user_role
- 用户和角色关联表 (用户和角色是多对多的关系)
-- 用户信息表
DROP TABLE IF EXISTS `t_sys_user`;
CREATE TABLE `t_sys_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`login_name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '登录账号',
`user_name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名称',
`email` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '用户邮箱',
`phone` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '手机号码',
`password` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '密码',
PRIMARY KEY (`id`),
UNIQUE KEY `UK_LOGIN_NAME` (`login_name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户信息表';
-- 角色信息表
DROP TABLE IF EXISTS `t_sys_role`;
CREATE TABLE `t_sys_role` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`role_name` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色名称',
`role_key` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色权限字符串',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色信息表';
-- 用户和角色关联表
DROP TABLE IF EXISTS `t_sys_user_role`;
CREATE TABLE `t_sys_user_role`
(
`user_id` bigint(20) unsigned NOT NULL COMMENT '用户ID',
`role_id` bigint(20) unsigned NOT NULL COMMENT '角色ID',
PRIMARY KEY (`user_id`, `role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户和角色关联表';
API设计
创建以下API:
URI | HTTP Method | 说明 |
---|---|---|
/ |
GET | 跳转到首页index.html |
/login |
GET | 跳转到登录页login.html |
/registration |
GET | 跳转到用户注册页registration.html |
/registration |
POST | 用户注册 |
应用配置
application.yaml
配置如下:
spring:
datasource:
url: jdbc:mysql://${
database-service:localhost}:3306/${
database-name:foxdb}?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
username: ${
database-user:foxuser}
password: ${
database-password:foxpassword}
driver-class-name: com.mysql.cj.jdbc.Driver
jpa:
show-sql: true
配置Spring Security
创建一个Spring Security配置类:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
/**
* Auth whitelist:
* - Static files
* - SwaggerUI for both Swagger2 and Swagger3
* https://stackoverflow.com/questions/37671125/how-to-configure-spring-security-to-allow-swagger-url-to-be-accessed-without-aut
* - registration
*
*/
private static final String [] AUTH_WHITELIST = {
"/js/**",
"/css/**",
"/img/**",
"/webjars/**",
"/registration**"
};
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(AUTH_WHITELIST).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
auth.setUserDetailsService(userService);
auth.setPasswordEncoder(passwordEncoder());
return auth;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
说明:
- 配置URI白名单,对白名单内的URI不需要登录,其它URI都需要登录。
- 配置了认证provider的UserDetailsService为
UserService
类,PasswordEncoder为BCryptPasswordEncoder
。
Web层
HomeController类
创建HomeController
类用来跳转到首页和登录页:
@Controller
public class HomeController {
@GetMapping("/")
public String home() {
return