【Spring Security】003-Spring Security web权限方案(1):用户认证
目录
一、用户认证
1、设置登录系统的账号、密码
方式一:通过配置文件
方式二:通过配置类
方式三:自定义编写实现类(常用)
2、通过查询数据库完成登录认证
技术点:
第一步:引入MybatisPlus相关依赖
第二步:创建数据库和数据库表
第三步:创建实体类
第四步:创建mapper,并创建UsersMapper接口
第五步:在MyUserDetailsService中调用mapper里面的方法,通过查询数据库进行用户认证
第六步:在启动类(或者配置类)添加@MapperScan注解
第七步:在配置文件application.properties中配置数据库
第八步:访问测试
3、自定义用户登录页面
第一步:修改配置类MySecurityConfig
第二步:创建login.html页面
第三步:在TestController添加index
第四步:访问测试
一、用户认证
1、设置登录系统的账号、密码
方式一:通过配置文件
在 application.properties里面进行配置:
server.port=8111
spring.security.user.name=zibo
spring.security.user.password=123456
方式二:通过配置类
代码演示:
package com.zibo.studyspringsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 对密码进行加密
String password = new BCryptPasswordEncoder().encode("123456");
// 设置账号和密码以及角色
auth.inMemoryAuthentication().withUser("zibo").password(password).roles("admin");
}
}
访问测试:
错误解决(修改配置类):
package com.zibo.studyspringsecurity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 对密码进行加密
String password = new BCryptPasswordEncoder().encode("123456");
// 设置账号和密码以及角色
auth.inMemoryAuthentication().withUser("zibo").password(password).roles("admin");
}
// 注入 PasswordEncoder 类到 spring 容器中
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
再次访问测试:
方式三:自定义编写实现类(常用)
概述:
前面的两种方法都不常用,实际项目中肯定是从数据库查询账号和密码;
步骤:
第一步:创建配置类,设置使用哪个userDetailsService实现类;
第二步:编写实现类,返回User对象,User对象有用户名、密码以及操作权限;
第一步代码演示:
package com.zibo.studyspringsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
// 注入 PasswordEncoder 类到 spring 容器中
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
第二步代码演示:
package com.zibo.studyspringsecurity.service;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// 此处仅作演示,实际项目中肯定是从数据库查询的
// 上面的参数String s是表单提取的用户名,我们可以通过用户名去数据库查数据
// 查到了返回,查不到就进行抛出异常或者进行页面跳转或者提示等操作
// 咱们在这里打印一下s看一下
System.out.println("表单提交的用户名是:" + s);
// 手动创建一个Collection<? extends GrantedAuthority> authorities 权限集合
// 实际项目中是从数据库查询的
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User("zibo",new BCryptPasswordEncoder().encode("123456"),auths); // 此处的auths不允许为空
}
}
访问测试:
2、通过查询数据库完成登录认证
技术点:
整合MybatisPlus完成查询数据库的操作;
第一步:引入MybatisPlus相关依赖
<?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.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zibo</groupId>
<artifactId>studyspringsecurity</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>studyspringsecurity</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--改成web工程-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--添加spring-security依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok 用来简化实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
第二步:创建数据库和数据库表
(下面一些数据库表是以后需要用到的,现在此统一创建出来)
创建数据库:
创建用户表:
CREATE TABLE users ( id BIGINT PRIMARY KEY auto_increment, username VARCHAR ( 20 ) UNIQUE NOT NULL, PASSWORD VARCHAR ( 100 ) );
添加用户数据:
INSERT INTO users
VALUES
( 1, '张三', '123456' );
INSERT INTO users
VALUES
( 2, '李四', '123456' );
创建角色表:
CREATE TABLE role ( id BIGINT PRIMARY KEY auto_increment, NAME VARCHAR ( 20 ) );
插入角色数据:
insert into role values(1,'管理员');
insert into role values(2,'普通用户');
创建用户_角色表:
CREATE TABLE role_user ( uid BIGINT, rid BIGINT );
插入用户_角色数据:
insert into role_user values(1,1);
insert into role_user values(2,2);
创建菜单表:
CREATE TABLE menu ( id BIGINT PRIMARY KEY auto_increment, NAME VARCHAR ( 20 ), url VARCHAR ( 100 ), parentid BIGINT, permission VARCHAR ( 20 ) );
插入菜单数据:
insert into menu values(1,'系统管理','',0,'menu:system');
insert into menu values(2,'用户管理','',0,'menu:user');
创建菜单_角色表:
CREATE TABLE role_menu ( mid BIGINT, rid BIGINT );
插入菜单_角色数据:
insert into role_menu values(1,1);
insert into role_menu values(2,1);
insert into role_menu values(2,2);
第三步:创建实体类
创建entity包,并创建Users实体类:
package com.zibo.studyspringsecurity.entity;
import lombok.Data;
@Data
public class Users {
private Integer id;
private String username;
private String password;
}
第四步:创建mapper,并创建UsersMapper接口
package com.zibo.studyspringsecurity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zibo.studyspringsecurity.entity.Users;
import org.springframework.stereotype.Repository;
@Repository // 不加会提示错误,但可以运行
public interface UsersMapper extends BaseMapper<Users> {
}
第五步:在MyUserDetailsService中调用mapper里面的方法,通过查询数据库进行用户认证
package com.zibo.studyspringsecurity.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zibo.studyspringsecurity.entity.Users;
import com.zibo.studyspringsecurity.mapper.UsersMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 调用usersMapper方法,根据用户名查询数据库
QueryWrapper<Users> wrapper = new QueryWrapper<>();
// 根据用户名查询
wrapper.eq("username",username);
Users users = usersMapper.selectOne(wrapper);
if(users==null){ // 数据库里面没有此用户名,认证失败
throw new UsernameNotFoundException("用户名不存在!");
}
// 手动创建一个Collection<? extends GrantedAuthority> authorities 角色权限集合
// 实际项目中是从数据库查询的
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
// 返回从数据库中查询到的账号、密码和角色信息
return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
}
}
第六步:在启动类(或者配置类)添加@MapperScan注解
package com.zibo.studyspringsecurity;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.zibo.studyspringsecurity.mapper")
public class StudyspringsecurityApplication {
public static void main(String[] args) {
SpringApplication.run(StudyspringsecurityApplication.class, args);
}
}
第七步:在配置文件application.properties中配置数据库
server.port=8111
# 设置security登录的账号密码
# spring.security.user.name=zibo
# spring.security.user.password=123456
# mysql 数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_security?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
第八步:访问测试
用户名:张三;密码:123456;
3、自定义用户登录页面
第一步:修改配置类MySecurityConfig
package com.zibo.studyspringsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
// 注入 PasswordEncoder 类到 spring 容器中
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 自定义自己编写的登录页面
// 登录页面设置
.loginPage("/login.html")
// 登录访问的路径,提交到的controller,不需要自己写
.loginProcessingUrl("/user/login")
// 登陆成功之后要跳转到的路径
.defaultSuccessUrl("/test/index").permitAll()
// 设置哪些路径不需要登陆就可以访问
.and().authorizeRequests().antMatchers("/","/test/hello","/user/login").permitAll()
.anyRequest().authenticated()
.and().csrf().disable(); // 关闭csrf防护
}
}
第二步:创建login.html页面
在resources目录下创建static目录,并创建login.html,name必须是username和password;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" action="/user/login">
用户名:<input type="text" name="username"/>
密码:<input type="text" name="password"/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
第三步:在TestController添加index
package com.zibo.studyspringsecurity.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public String hello(){
return "Hello Spring Security!";
}
@GetMapping("/index")
public String index(){
return "登录成功!";
}
}
第四步:访问测试
访问http://localhost:8111/test/hello
访问http://localhost:8111/test/index
登录测试:
还没有评论,来说两句吧...