1.Spring Security框架简介
Spring 是非常流行和成功的 Java 应用开发框架,Spring Security 正是 Spring 家族中的 成员。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方 案。
正如你可能知道的关于安全方面的两个主要区域是“认证”和“授权”(或者访问控 制),一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权 (Authorization)两个部分,这两点也是 Spring Security 重要核心功能。
(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问 该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认 证过程。通俗点说就是系统认为用户是否能登录
(2)用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户 所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以 进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的 权限。通俗点讲就是系统判断用户是否有权限去做某些事情。
2.开始SpringSecurity入门案例
2.1.创建项目
首先创建一个SpringBoot项目
选择我们项目所需要的两个组件,在创建项目的时候会自动在pom文件中加入相关的依赖,不需要我们手动去添加依赖
直接点击Fish创建项目
打开pom文件可以发现SpringWeb和SpringSecurity的相关依赖已经自动添加进去了
2.2、编写项目
在com.hopu路径下创建controller文件夹,创建TestController.java 文件,编写以下代码,接收浏览器发送的hello请求,返回hello,Spring Security!
@RestController
public class TesrController {
@RequestMapping("/hello")
public String hello(){
return "hello,Spring Security!";
}
}
为了防止端口号有冲突,在application.properties配置文件中将端口号更改为8888
#更改端口号为8888
server.port=8888
打开DemoApplication运行main方法,在浏览器输入localhost:8888/hello。访问得到的页面没有返回hello,Spring Security!而是出现了登录表单,这证明Security已经整合进去了,这是其自带的表单样式
用户名默认为user
密码在项目启动的时候在控制台会打印,注意每次启动的时候密码都会发生变化!
输入用户名和密码就可以访问了
这样一个入门案例就写好了,我们会发现用户名被定死了,密码是控制台随机生成很不方便,对于我们的使用不够友好,下面我们就来讲解一下怎么去更改用户名和密码
3.设置登录的用户名和密码
3.1、方式一:通过application.properties
通过配置文件设置用户名和密码
spring.security.user.name=atguigu
spring.security.user.password=atguigu
3.2、方式二:通过配置类
开始前将之前通过方式一设置的用户名和密码注释掉
在com.hopu包下创建一个config包,创建一个名叫SecurityConfig的配置类
- 在类上面加一个注解@Configuration
- SecurityConfig类继承Security中提供的一个WebSecurityConfigurerAdapter类
- 重写config方法;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//重写config方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//使用PasswordEncoder接口中的方法将密码加密
BCryptPasswordEncoder passwordEncoder =new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123456");
//使用auth来设置用户名和密码,roles里表示用户身份
auth.inMemoryAuthentication().withUser("Lucy").password(password).roles("admin");
}
//因为加密密码默认使用PasswordEncoder接口,需要创建它的一个对象
@Bean
PasswordEncoder password(){
return new BCryptPasswordEncoder();
}
}
第三种方式自定义实现类设置
将之前的写的SecurityConfig配置类注释掉,方便对比
第一步创建配置类
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中 账号和密码都是从数据库中查询出来的。 所以我们要通过自定义逻辑控制认证逻辑。
package com.hopu.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 SecurityConfigTest extends WebSecurityConfigurerAdapter {
//注入UserDetailsService 实现类
@Autowired
private UserDetailsService userDetailsService;
//重写config方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
//因为加密密码默认使用PasswordEncoder接口,需要创建它的一个对象
@Bean
PasswordEncoder password(){
return new BCryptPasswordEncoder();
}
第二步编写实现类
在com.hopu包下创建service包,在service包下创建MyUserDetailsService实现类
编写代码
- 使用@Service注解将userDetailsService注入到这个实现类上
package com.hopu.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hopu.entity.Users;
import com.hopu.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 org.springframework.stereotype.Service;
import java.util.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//由于权限是一个集合,所以用集合写权限
List<GrantedAuthority> auths=
AuthorityUtils.commaSeparatedStringToAuthorityList("a1");
//User是security里的包,不是实现类
//第一个值是用户名,第二个值是密码,第三个值是权限,不能为空
return new User("lucy",newBCryptPasswordEncoder().encode("123"),auths);
后面进行测试
第四种方式
第一步创建数据库
创建数据库demo,并创建users表(表名需要跟后面调用的对象名相同,不然无法正常调用数据库中的数据)并添加数据
第二步:引入相关依赖
在pom中引入mybatis-plus和mysql的依赖,这两个依赖必须引入,lombok依赖可以不引入,不引入我们也可以靠代码实现它的功能,但是lombok可以简化代码
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
第一次使用lombok需要手动下载其相关组件
由于我已经下好了lombok所以我这里没有下载按钮,没有下载的在箭头指向的位置会有按钮
第三步:编写实体类
- 在com.hopu包下创建entity包,创建Users实体类,
- 编写USers实体类,返回Users对象,Users对象有用户名密码和从操作权限
package com.hopu.entity;
import lombok.Data;
@Data
public class Users {
private Integer id;
private String username;
private String password;
private String authority;
}
@Data注释是lombok组件里的,自动生成get set等方法
第四步:整合mybatis-plus,创建接口,继承mybatis-plus
创建mapper包,在这个包下创建名为UsersMapper的接口
- 让这个接口继承mybatis-plus中的BaseMapper接口,<>中加上泛型,就是实体类Users
- BaseMapper接口里封装了针对数据库的增删改查的操作
- 我们只需要继承BaseMapper接口,调用其中的方法就能做到增删改查的功能
package com.hopu.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hopu.entity.Users;
import org.springframework.stereotype.Repository;
public interface UsersMapper extends BaseMapper<Users> {
}
第五步:在MyUserDetailsService中调用mapper方法查询数据库进行认证
- 将UsersMapper注入MyUserDetailsService中
- 注入后发现usersMapper报错了,这是因为UsersMapper是接口,所以我们在UsersMapper的类上加上一个注解@Repository
- 使用mybatis-plus中的构造器QueryWrapper查询数据库
- 使用Users users=usersMapper.selectOne(wrapper);查询数据库得到一条记录
- 将写死的用户名和密码改为从数据库中获取的用户名和密码
package com.hopu.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hopu.entity.Users;
import com.hopu.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 {
//注入UsersMapper
@Autowired
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<Users> wrapper = new QueryWrapper<>();
wrapper.eq("username",username);
Users users=usersMapper.selectOne(wrapper);
if (users==null){
throw new UsernameNotFoundException("用户不存在");
}
List<GrantedAuthority> auths= AuthorityUtils.commaSeparatedStringToAuthorityList(users.getAuthority());
return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
}
}
最后进行测试即可。