Spring?Security實(shí)現(xiàn)用戶名密碼登錄詳解
環(huán)境
JDK 1.8
Spring Boot 2.3.0.RELEASE
Maven 3.6.1
H2 數(shù)據(jù)庫
用戶名密碼登錄
首先,我們用 Spring Security 實(shí)現(xiàn)用戶輸入用戶名密碼登錄驗(yàn)證并獲取相應(yīng)權(quán)限。
E-R圖
完整建表語句
因?yàn)槭菧y(cè)試程序,所以用H2數(shù)據(jù)庫來測(cè)試。SQL腳本在resouces/db目錄下,項(xiàng)目啟動(dòng)后會(huì)自動(dòng)初始化腳本,無需手動(dòng)執(zhí)行。
schema.sql
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
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);
準(zhǔn)備好建表語句后,完成實(shí)體類的編寫
SysRole.java
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
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
package org.hui.login.model; /** * 角色和用戶對(duì)應(yīng)關(guān)系 * @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;} }
以上,完成了數(shù)據(jù)層的設(shè)計(jì)。
POM依賴
<?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.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>example</groupId> <artifactId>spring-login</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-login</name> <description>Spring Security to implements Login</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置文件
application.properties
spring.datasource.url=jdbc:h2:mem:userdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=123 #設(shè)置SQL腳本的位置,resources/db目錄下,如果不設(shè)置的話,默認(rèn)就在resources目錄下 spring.datasource.schema=classpath:db/schema.sql spring.datasource.data=classpath:db/data.sql #H2控制臺(tái)啟用 spring.h2.console.enabled=true #訪問H2的URL spring.h2.console.path=/h2 # 下劃線轉(zhuǎn)化為駝峰命名 mybatis.configuration.map-underscore-to-camel-case=true
Mapper
采用了Mybatis來操作數(shù)據(jù)庫。
準(zhǔn)備好需要的幾個(gè)Mapper,如下
SysRoleMapper.java
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
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
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<SysUserRole> listByUserId(Integer userId); }
Service設(shè)計(jì)
Spring Security提供了一個(gè)UserDetailsService接口,我們需要實(shí)現(xiàn)這個(gè)接口的loadUserByUsername方法,用于用戶信息的獲取,如果存在用戶,則把用戶的密碼獲取出來,如果不存在這個(gè)用戶,直接拋異常。
我們新建一個(gè)SysUserDetailService.java
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<GrantedAuthority> authorities = new ArrayList<>(); // 從數(shù)據(jù)庫中取出用戶信息 SysUser user = sysUserMapper.selectByName(username); // 判斷用戶是否存在 if(user == null) { throw new UsernameNotFoundException("用戶名不存在"); } // 添加權(quán)限 List<SysUserRole> userRoles = sysUserRoleMapper.listByUserId(user.getId()); for (SysUserRole userRole : userRoles) { SysRole role = sysRoleMapper.selectById(userRole.getRoleId()); authorities.add(new SimpleGrantedAuthority(role.getName())); } // 返回UserDetails實(shí)現(xiàn)類 return new User(user.getName(), user.getPassword(), authorities); } }
如果用戶存在,則會(huì)進(jìn)行密碼的校驗(yàn),方便起見,密碼我們假設(shè)儲(chǔ)存為明文,實(shí)際上密碼有很多加密的策略,這個(gè)后序可以自己配置,密碼校驗(yàn)在SecurityConfig這個(gè)類中,代碼如下:
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(); // 關(guān)閉CSRF跨域 http.csrf().disable(); } @Override public void configure(WebSecurity web) { web.ignoring().antMatchers("/css/**", "/js/**"); } }
以上便完成了所有后端代碼的編寫,接下來,完成controller和前端頁面的編寫。
HTML
在resources的static目錄下,新建兩個(gè)html文件
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登錄頁</title> </head> <body> <form action="/login" method="post"> 用戶名:<input type="text" name="username"> 密碼:<input type="password" name="password"> <button type="submit">登錄</button> </form> </body> </html>
home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>主頁</title> </head> <body> 登錄成功 </body> </html>
Controller
新建一個(gè)LoginController,用于接收前端請(qǐng)求
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"; } }
啟動(dòng)
運(yùn)行以下主程序
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
顯示登錄頁面,輸入用戶名密碼,點(diǎn)擊登錄,即可看到效果。
完整代碼
以上就是Spring Security實(shí)現(xiàn)用戶名密碼登錄詳解的詳細(xì)內(nèi)容,更多關(guān)于Spring Security用戶名密碼登錄的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java多線程鎖機(jī)制相關(guān)原理實(shí)例解析
這篇文章主要介紹了Java多線程鎖機(jī)制相關(guān)原理實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08spring源碼學(xué)習(xí)之bean的初始化以及循環(huán)引用
這篇文章主要給大家介紹了關(guān)于spring源碼學(xué)習(xí)之bean的初始化以及循環(huán)引用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10火遍全網(wǎng)的Hutool使用Builder模式創(chuàng)建線程池的方法
這篇文章主要介紹了火遍全網(wǎng)的Hutool使用Builder模式創(chuàng)建線程池的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解
這篇文章主要為大家介紹了性能爆棚的實(shí)體轉(zhuǎn)換復(fù)制工具M(jìn)apStruct使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Mybatis-Plus實(shí)體類注解方法與mapper層和service層的CRUD方法
CRUD是指在做計(jì)算處理時(shí)的增加(Create)、讀取查詢(Retrieve)、更新(Update)和刪除(Delete)幾個(gè)單詞的首字母簡寫。主要被用在描述軟件系統(tǒng)中DataBase或者持久層的基本操作功能,下面讓我們一起看看吧2022-03-03帶你走進(jìn)Maven的大門-最全Maven配置及集成idea工具總結(jié)
Maven項(xiàng)目對(duì)象模型(POM),是一個(gè)項(xiàng)目管理工具可以通過一小段描述信息來管理項(xiàng)目的構(gòu)建,報(bào)告和文檔的軟件.那我們想要在IDEA中使用Maven得進(jìn)行一些配置,接下來我們具體看一下是如何配置使用的,需要的朋友可以參考下2021-06-06使用Spring Security集成手機(jī)驗(yàn)證碼登錄功能實(shí)現(xiàn)
本文詳細(xì)介紹了如何利用SpringSecurity來實(shí)現(xiàn)手機(jī)驗(yàn)證碼的注冊(cè)和登錄功能,在登錄過程中,同樣需通過驗(yàn)證碼進(jìn)行驗(yàn)證,文章還提供了相關(guān)的代碼實(shí)現(xiàn)2024-10-10