环境
JDK 1.8
Spring Boot 2.3.0.RELEASE
Maven 3.6.1
H2 数据库
用户名密码登录
首先,我们用 Spring Security 实现用户输入用户名密码登录验证并获取相应权限。
E-R图
完整建表语句
因为是测试程序,所以用H2数据库来测试。SQL脚本在resouces/db目录下,项目启动后会自动初始化脚本,无需手动执行。
schema.sql
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | DROP TABLE IF EXISTS `SYS_ROLE`; DROP TABLE IF EXISTS `SYS_USER_ROLE`; DROP TABLE IF EXISTS `SYS_USER`; create table SYS_ROLE ( ID INT not null primary key , NAME VARCHAR (255) not null ); create table SYS_USER ( ID INT not null primary key , NAME VARCHAR not null , PASSWORD VARCHAR (255) not null ); create table SYS_USER_ROLE ( USER_ID INT not null , ROLE_ID INT not null , constraint pk_1 primary key (ROLE_ID, USER_ID), constraint fk_1 foreign key (ROLE_ID) references SYS_ROLE (ID) on update cascade on delete cascade , constraint fk_2 foreign key (USER_ID) references SYS_USER (ID) on update cascade on delete cascade ); |
data.sql
1 2 3 | INSERT INTO `SYS_ROLE` (`ID`, ` NAME `) VALUES (1, 'ADMIN' ),(2, 'USER' ); INSERT INTO `SYS_USER` (`ID`, ` NAME `, ` PASSWORD `) VALUES (1, 'super' , '888888' ), (2, 'jack' , '666666' ), (3, 'lucy' , '999999' ); INSERT INTO `SYS_USER_ROLE` (`USER_ID`, `ROLE_ID`) VALUES (1, 1),(2, 2),(3, 2); |
准备好建表语句后,完成实体类的编写
SysRole.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package org.hui.login.model; /** * 用户角色 * @author zenghui * @date 2020-05-20 */ public class SysRole { private Integer id; private String name; public Integer getId() { return id;} public void setId(Integer id) { this .id = id;} public String getName() { return name;} public void setName(String name) { this .name = name;} } |
SysUser.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | package org.hui.login.model; /** * 用户基本信息 * @author zenghui * @date 2020-05-20 */ public class SysUser { private Integer id; private String name; private String password; public Integer getId() { return id;} public void setId(Integer id) { this .id = id;} public String getName() { return name;} public void setName(String name) { this .name = name;} public String getPassword() { return password;} public void setPassword(String password) { this .password = password;} } |
SysUserRole.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package org.hui.login.model; /** * 角色和用户对应关系 * @author zenghui * @date 2020-05-20 */ public class SysUserRole { private Integer userId; private Integer roleId; public Integer getUserId() { return userId;} public void setUserId(Integer userId) { this .userId = userId;} public Integer getRoleId() { return roleId;} public void setRoleId(Integer roleId) { this .roleId = roleId;} } |
以上,完成了数据层的设计。
POM依赖
1 | 4.0.0org.springframework.bootspring-boot-starter-parent2.3.0.RELEASEexamplespring-login0.0.1-SNAPSHOTspring-loginSpring Security to implements Login1.8org.springframework.bootspring-boot-starter-securityorg.mybatis.spring.bootmybatis-spring-boot-starter2.1.2org.springframework.bootspring-boot-starter-webcom.h2databaseh2runtimeorg.springframework.bootspring-boot-maven-plugin |
配置文件
application.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | spring.datasource.url=jdbc:h2:mem:userdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=123 #设置SQL脚本的位置,resources/db目录下,如果不设置的话,默认就在resources目录下 spring.datasource.schema=classpath:db/schema.sql spring.datasource.data=classpath:db/data.sql #H2控制台启用 spring.h2.console.enabled=true #访问H2的URL spring.h2.console.path=/h2 # 下划线转化为驼峰命名 mybatis.configuration.map-underscore-to-camel-case=true |
Mapper
采用了Mybatis来操作数据库。
准备好需要的几个Mapper,如下
SysRoleMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 | package org.hui.login.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.hui.login.model.SysRole; /** * @author zenghui * @date 2020-05-20 */ @Mapper public interface SysRoleMapper { @Select ( "SELECT * FROM sys_role WHERE id = #{id}" ) SysRole selectById(Integer id); } |
SysUserMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package org.hui.login.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.hui.login.model.SysUser; /** * @author zenghui * @date 2020-05-20 */ @Mapper public interface SysUserMapper { @Select ( "SELECT * FROM sys_user WHERE name = #{name}" ) SysUser selectByName(String name); } |
SysUserRoleMapper.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package org.hui.login.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import org.hui.login.model.SysUserRole; import java.util.List; /** * @author zenghui * @date 2020-05-20 */ @Mapper public interface SysUserRoleMapper { @Select ( "SELECT * FROM sys_user_role WHERE user_id = #{userId}" ) List listByUserId(Integer userId); } |
Service设计
Spring Security提供了一个UserDetailsService接口,我们需要实现这个接口的loadUserByUsername方法,用于用户信息的获取,如果存在用户,则把用户的密码获取出来,如果不存在这个用户,直接抛异常。
我们新建一个SysUserDetailService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package org.hui.login.service; import org.hui.login.mapper.SysRoleMapper; import org.hui.login.mapper.SysUserMapper; import org.hui.login.mapper.SysUserRoleMapper; import org.hui.login.model.SysRole; import org.hui.login.model.SysUser; import org.hui.login.model.SysUserRole; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; 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.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * @author zenghui * @date 2020-05-20 */ @Service public class SysUserDetailService implements UserDetailsService { private final SysUserMapper sysUserMapper; private final SysRoleMapper sysRoleMapper; private final SysUserRoleMapper sysUserRoleMapper; public SysUserDetailService(SysUserMapper sysUserMapper, SysRoleMapper sysRoleMapper, SysUserRoleMapper sysUserRoleMapper) { this .sysUserMapper = sysUserMapper; this .sysRoleMapper = sysRoleMapper; this .sysUserRoleMapper = sysUserRoleMapper; } @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { Collection authorities = new ArrayList(); // 从数据库中取出用户信息 SysUser user = sysUserMapper.selectByName(username); // 判断用户是否存在 if (user == null ) { throw new UsernameNotFoundException( "用户名不存在" ); } // 添加权限 List userRoles = sysUserRoleMapper.listByUserId(user.getId()); for (SysUserRole userRole : userRoles) { SysRole role = sysRoleMapper.selectById(userRole.getRoleId()); authorities.add( new SimpleGrantedAuthority(role.getName())); } // 返回UserDetails实现类 return new User(user.getName(), user.getPassword(), authorities); } } |
如果用户存在,则会进行密码的校验,方便起见,密码我们假设储存为明文,实际上密码有很多加密的策略,这个后序可以自己配置,密码校验在SecurityConfig这个类中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | package org.hui.login.config; import org.hui.login.service.SysUserDetailService; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.PasswordEncoder; /** * @author zenghui * @date 2020-05-20 */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity (prePostEnabled = true ) public class SecurityConfig extends WebSecurityConfigurerAdapter { private final SysUserDetailService sysUserDetailService; public SecurityConfig(SysUserDetailService sysUserDetailService) { this .sysUserDetailService = sysUserDetailService; } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(sysUserDetailService).passwordEncoder( new PasswordEncoder() { @Override public String encode(CharSequence charSequence) { return charSequence.toString(); } @Override public boolean matches(CharSequence charSequence, String s) { return s.equals(charSequence.toString()); } }); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().anyRequest().authenticated() .and().formLogin().loginPage( "/login" ).defaultSuccessUrl( "/" ).permitAll() .and().logout().permitAll(); // 关闭CSRF跨域 http.csrf().disable(); } @Override public void configure(WebSecurity web) { web.ignoring().antMatchers( "/css/**" , "/js/**" ); } } |
以上便完成了所有后端代码的编写,接下来,完成controller和前端页面的编写。
HTML
在resources的static目录下,新建两个html文件
login.html
1 | < title >登录页</ title > |
用户名:
密码:
home.html
1 2 | < title >主页</ title > 登录成功 |
Controller
新建一个LoginController,用于接收前端请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package org.hui.login.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @author zenghui * @date 2020-05-20 */ @Controller public class LoginController { @RequestMapping ( "/" ) public String home() { return "home.html" ; } @RequestMapping ( "/login" ) public String login() { return "login.html" ; } } |
启动
运行以下主程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package org.hui.login; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * @author zenghui * @date 2020-05-20 */ @SpringBootApplication public class LoginApplication { public static void main(String[] args) { SpringApplication.run(LoginApplication. class , args); } } |
访问 http://localhost:8080/login
显示登录页面,输入用户名密码,点击登录,即可看到效果。
完整代码
以上就是Spring Security实现用户名密码登录详解的详细内容,更多关于Spring Security用户名密码登录的资料请关注IT俱乐部其它相关文章!