【开源项目--稻草】Day01、Day02
1.项目描述
一个简单的论坛项目
项目最终结构
2.创建项目
1.2.
3.修改pom文件
改写父类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.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>jd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jd</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
</properties>
</project>
4. 创建子项目
修改子项目pom.xml文件
<parent>
<groupId>cn.tedu</groupId>
<artifactId>jd</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
修改父项目pom.xml文件
<packaging>pom</packaging>
<modules>
<module>jd-shop</module>
</modules>
5.通用项目结构
5.1 lombok
- 什么是lombok
一个能够简化实体类代码的工具
使用lombok可以让我们编写的实体类只需要必要的属性声明即可
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
安装插件
- 创建实体类
@Getter//生成get方法
@Setter//生成set方法
@ToString//重写toString
@EqualsAndHashCode//重写equals和hashCode
@NoArgsConstructor//生成无参构造
@AllArgsConstructor//生成全参构造
//@Data=@Getter+@Setter+@ToString+@EqualsAndHashCode+默认情况下的无参构造
@Slf4j//启动日志,在这个类的任何方法中可以使用log对象记录日志
public class Msg {
private Integer id;
private String name;
private String content;
}
5.2 MyBatisPlus
-
什么是MyBatisPlus
就是在MyBatis框架的基础上延伸了一些新的功能的框架
使用MyBatisPlus不用再导入Mybatis的依赖了
-
为什么要用MyBatisPlus
就是MyBatisPlus增加了更多功能,方便我们处理数据 -
怎么使用MyBatisPlus
找到父项目的pom.xml文件添加一个版本依赖和依赖管理
代码如下
<?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.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>straw</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>straw</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>straw-portal</module>
</modules>
<properties>
<java.version>1.8</java.version>
<mybatis.plus.version>3.3.1</mybatis.plus.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis.plus.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
子项目的pom.xml文件使用这些依赖
代码如下
<?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>cn.tedu</groupId>
<artifactId>straw</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>straw-portal</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>straw-portal</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>
- MyBatisPlus使用体验
创建一个实体类使用MyBatisPlus
创建Tag实体类代码如下
@Data
public class Tag {
private Integer id;
private String name;
private String createBy;
private String createTime;
}
创建这个实体类对应的Mapper接口
TagMapper代码如下
//BaseMapper接口是MyBatisPlus提供的
//其中包含着一些最基本的查询
public interface TagMapper extends BaseMapper<Tag> {
}
不要忘了在配置类中配置扫描@MapperScan
@SpringBootApplication
@MapperScan("cn.tedu.straw.portal.mapper")
public class StrawPortalApplication {
public static void main(String[] args) {
SpringApplication.run(StrawPortalApplication.class, args);
}
}
配置application.properties
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/straw?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
spring.datasource.username=root
spring.datasource.password=root
logging.level.cn.tedu.straw.portal.mapper=trace
6.straw-generator
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-extension</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
创建一个类CodeGenerator类中复制
package cn.tedu.generator;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
/**
* @Description: 代码生成类
*/
public class CodeGenerator {
//数据库连接参数
public static String driver = "com.mysql.cj.jdbc.Driver";
public static String url = "jdbc:mysql://localhost:3306/straw?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true";
public static String username="root";
public static String password="root";
//父级别包名称
public static String parentPackage = "cn.tedu.straw";
//代码生成的目标路径
public static String generateTo = "/straw-generator/src/main/java";
//mapper.xml的生成路径
public static String mapperXmlPath = "/straw-generator/src/main/resources/mapper";
//控制器的公共基类,用于抽象控制器的公共方法,null值表示没有父类
public static String baseControllerClassName ;// = "cn.tedu.straw.portal.base.BaseController";
//业务层的公共基类,用于抽象公共方法
public static String baseServiceClassName ; // = "cn.tedu.straw.portal.base.BaseServiceImpl";
//作者名
public static String author = "tedu.cn";
//模块名称,用于组成包名
public static String modelName = "portal";
//Mapper接口的模板文件,不用写后缀 .ftl
public static String mapperTempalte = "/ftl/mapper.java";
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotEmpty(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
/**
* RUN THIS
*/
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + generateTo);
gc.setAuthor(author);
gc.setOpen(false);
//设置时间类型为Date
gc.setDateType(DateType.TIME_PACK);
//开启swagger
//gc.setSwagger2(true);
//设置mapper.xml的resultMap
gc.setBaseResultMap(true);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl(url);
// dsc.setSchemaName("public");
dsc.setDriverName(driver);
dsc.setUsername(username);
dsc.setPassword(password);
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setEntity("model");
//pc.setModuleName(scanner("模块名"));
pc.setModuleName(modelName);
pc.setParent(parentPackage);
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.ftl") {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输入文件名称
return projectPath + mapperXmlPath
+ "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
mpg.setTemplate(new TemplateConfig().setXml(null));
mpg.setTemplate(new TemplateConfig().setMapper(mapperTempalte));
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setNaming(NamingStrategy.underline_to_camel);
//字段驼峰命名
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//设置实体类的lombok
strategy.setEntityLombokModel(true);
//设置controller的父类
if (baseControllerClassName!=null) strategy.setSuperControllerClass(baseControllerClassName);
//设置服务类的父类
if (baseServiceClassName !=null ) strategy.setSuperServiceImplClass(baseServiceClassName);
// strategy.
//设置实体类属性对应表字段的注解
strategy.setEntityTableFieldAnnotationEnable(true);
//设置表名
String tableName = scanner("表名, all全部表");
if(! "all".equalsIgnoreCase(tableName)){
strategy.setInclude(tableName);
}
strategy.setTablePrefix(pc.getModuleName() + "_");
strategy.setRestControllerStyle(true);
mpg.setStrategy(strategy);
// 选择 freemarker 引擎需要指定如下加,注意 pom 依赖必须有!
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
在resources中创建ftl文件夹,文件夹中创建mapper.java.ftl文件
import ${package.Entity}.${entity};
import ${superMapperClassPackage};
import org.springframework.stereotype.Repository;
/**
* <p>
* ${table.comment!} Mapper 接口
* </p>
*
* @author ${author}
* @since ${date}
*/
<#if kotlin>
interface ${table.mapperName} : ${superMapperClass}<${entity}>
<#else>
@Repository
public interface ${table.mapperName} extends ${superMapperClass}<${entity}> {
}
</#if>
7.Spring-Security
Spring-Security(Spring安全框架)是Spring提供的安全管理组件
是Spring框架环境下提供的安全管理和权限管理的组件
一个项目一般都会有登录功能,我们之前编写的登录功能非常简陋,不能用于实际开发
Spring-Security提供了专业的实现登录的方式,供我们使用
7.1 使用Spring-Security实现登录
基本使用
步骤1:
导入依赖
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Security Test -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
步骤2:启动服务
在启动服务的控制台信息中会包含一个随机产生的密码
用于登录Spring-Security框架
用默认的用户名是"user"
密码赋值控制台出现的,粘贴登录即可
步骤3:
我们不想用它提供的用户名和密码,就可以自己设置
application.properties文件中添加配置如下
# Spring-Security配置用户名密码
spring.security.user.name = admin
spring.security.user.password = 123456
步骤4:
密码加密
实际开发中,一定不可能在任何位置保存明文密码
将用户的密码经过加密之后再保存,能够最大限度的提高密码的安全级别
而加密的过程不需要我们编写,使用现成的加密规则即可
我们使用BCrypt
的加密规则
首先我们新建一个包cn.tedu.straw.portal.security
配置类SecurityConfig
,在这个类中注入加密对象
代码如下
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//@Configuration表示当前类是配置类,可能向Spring容器中注入对象
@Configuration
public class SecurityConfig {
//注入一个加密对象
@Bean
public PasswordEncoder passwordEncoder(){
//这个加密对象使用BCrypt加密内容
return new BCryptPasswordEncoder();
}
}
步骤5:
下面进行测试,测试加密功能和验证功能
代码如下
@SpringBootTest
public class SecurityTest {
@Autowired
PasswordEncoder passwordEncoder;
@Test
public void encodeTest(){
/*
每次运行加密结果不同
是因为加密对象采用了"随机加盐"技术,提高安全性
*/
String pwd=passwordEncoder.encode("123456");
System.out.println(pwd);
//$2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW
}
@Test
public void matchTest(){
/*
验证我们输入的密码是不是能匹配生成的密文
*/
boolean b=passwordEncoder.matches("123456",
"$2a$10$IHMiKBqpiPFYgRg4P0E0" +
"HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW");
System.out.println(b);
}
}
步骤6:
修改application.properties文件中配置的密码
# Spring-Security配置用户名密码
spring.security.user.name = admin
spring.security.user.password = $2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW
测试登录…
步骤7:
上面的操作可以简化
将一个Spring内置的算法标记标注在application.properties
文件的密文密码前
代码如下
# Spring-Security配置用户名密码
spring.security.user.name=admin
spring.security.user.password={bcrypt}$2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW
安照上面的配置,我们刚刚注入的PasswordEncoder对象就可以省略了
//注入一个加密对象(密码中设定了算法ID下面的注入就省略了!)
/*@Bean
public PasswordEncoder passwordEncoder(){
//这个加密对象使用BCrypt加密内容
return new BCryptPasswordEncoder();
}*/
8.权限管理
有些网页必须登录之后才能访问
即使都是登录用户,它们也有可能有身份的区别,不同身份有不同功能
只有学生才能访问发布问题的页面,
只有老师才能访问回答问题的页面
Spring-Security也方便我们来管理这些问题
下面我们就使用Spring-Security权限管理功能访问用户信息
步骤1:开启权限管理功能
SecurityConfig这类中编写代码
// @Configuration表示当前类是配置类,可能向Spring容器中注入对象
@Configuration
// 下面的注解表示通知Spring-Security开启权限管理功能
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
//方法中配置哪个用户可以有什么样的权限
auth.inMemoryAuthentication().withUser("Tom")
.password("{bcrypt}$2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW")
.authorities("/tag/get");
}
}
步骤2:
在Controller类的方法上声明访问这个方法需要什么权限
如果访问这个方法需要"/tag/get"权限,那么没有这个权限的人就不能访问
如果Controller类的方法上没有声明权限,那么就是登录的用户都可以访问
在TagController类中编写一些权限
代码如下
@RestController
//下面的注解表示想访问本控制器中的任何方法需要前缀/portal/tag
@RequestMapping("/portal/tag")
public class TagController {
@Autowired
private IUserService userService;
@Autowired
private ITagService tagService;
@GetMapping("/get")//localhost/portal/tag/get?id=3
@PreAuthorize("hasAuthority('/tag/get')")
public User get(Integer id){
return userService.getById(3);
}
// 编写一套可以按tagid查询一个tag信息的控制器方法
// 将tag信息显示在浏览器
@GetMapping("/gettag")
@PreAuthorize("hasAuthority('/tag/byid')")
public Tag getTag(Integer id){
return tagService.getById(id);
}
}
测试运行
tom正常访问/get?id=3
访问/gettag?id=14时发生403错误,表示权限不足
现在Tom用户不能访问的localhost/portal/tag/gettag路径,因为他没有权限
我们可以通过配置将这个权限赋予Tom用户
方法如下
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//方法中配置哪个用户可以有什么样的权限
auth.inMemoryAuthentication().withUser("Tom")
.password("{bcrypt}$2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW")
.authorities("/tag/get","/tag/byid");
}
8.1 使用UserDetailsService提供认证数据
我们service包中编写一个类UserDetailsServiceImpl
代码如下
/**
* 这个类实现UserDetailsService接口
* 为Spring-Security提供认证的数据
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
// Spring-Security认证信息时
// 会将用户名传递到这个方法中
// 根据这个用户名获得数据库中加密的密码,
// 如果匹配则登录成功
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
//这个方法返回的是用户的详细信息
UserDetails user=null;
//暂时规定正确的用户名和密码是"Jerry",加密的"123456"
if("Jerry".equals(username)){
//如果用户名正确,将加密的密码保存到User对象
//下面的User类也是Spring提供的不是我们的实体类
user= User.builder()
.username("Jerry")
.password("{bcrypt}$2a$10$IHMiKBqpiPFYgRg4P0E0HeU.xdkr1nw0/y1AWKIvHh5TMNwxVuBRW")
//这里也能直接赋予权限
.authorities("/tag/get")
.build();
}
System.out.println("user:"+user);
return user;
}
}
回到SecurityConfig类中,删除configer方法之前的代码
将方法改写为:
// @Configuration表示当前类是配置类,可能向Spring容器中注入对象
@Configuration
// 下面的注解表示通知Spring-Security开启权限管理功能
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends
WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService);
}
}
8.2 关于用户的权限
数据库中有:
permission表,保存权限
role表,保存角色
role_permission表,保存角色和权限的关系
role是permission多对多关系,多对多关系的表一定会出现一张中间表,来保存他们的关系
user表,保存用户信息
user_role表,保存用户和角色的关系
user和role表也是多对多的关系
我们在登录用户时需要指定用户的权限,根据用户的id查询权限可能需要使用这5张表的连接查询
除了对权限的查询外,还需要用户的基本信息,使用用户名查询出用户对象即可
在UserMapper接口中添加如下两个查询
@Repository
public interface UserMapper extends BaseMapper<User> {
//根据用户输入的用户名查询用户信息的方法
@Select("select * from user where username=#{username}")
User findUserByUsername(String username);
//查询指定id的用户的所有权限
@Select("SELECT p.id,p.name" +
" FROM user u" +
" LEFT JOIN user_role ur ON u.id=ur.user_id" +
" LEFT JOIN role r ON r.id=ur.role_id" +
" LEFT JOIN role_permission rp ON r.id=rp.role_id" +
" LEFT JOIN permission p ON p.id=rp.permission_id" +
" WHERE u.id=#{id}")
List<Permission> findUserPermissionsById(Integer id);
}
最好还是测试一下,保证万无一失!
测试代码如下
@Autowired
UserMapper userMapper;
@Test
public void findUser(){
User user = userMapper.findUserByUsername("tc2");
System.out.println(user);
}
@Test
public void findPermissions(){
List<Permission> list = userMapper.findUserPermissionsById(3);
for(Permission p: list){
System.out.println(p);
}
}
8.3 连接数据库实现Spring-Security登录
步骤1:
在编写IUserService接口中添加一个获得用户详情的方法
public interface IUserService extends IService<User> {
//这个方法用法查询获得用户详情对象的业务
//UserDetails是SpringSecurity验证用户必要的信息
//String username是SpringSecurity接收的用户输入的用户名
UserDetails getUserDetails(String username);
}
步骤2:
在impl包下的UserServiceImpl类中实现这个方法
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails getUserDetails(String username) {
//根据用户名获得用户对象
User user=userMapper.findUserByUsername(username);
//判断用户对象是否为空
if(user==null) {
//如果为空直接返回null
return null;
}
//如果不为空根据用户的id查询这个用户的所有权限
List<Permission> permissions=
userMapper.findUserPermissionsById(user.getId());
//将权限List中的权限转成数组方便赋值
String[] auths=new String[permissions.size()];
for(int i=0;i<auths.length;i++){
auths[i]=permissions.get(i).getName();
}
//创建UserDetails对象,并为他赋值
UserDetails ud= org.springframework.security.core.userdetails
.User.builder()
.username(user.getUsername())
.password(user.getPassword())
.accountLocked(user.getLocked()==1)//写==1是判断锁定
.disabled(user.getEnabled()==0)//写==0是判断不可用
.authorities(auths).build();
//最后返回UserDetails对象
return ud;
}
}
步骤3:测试代码
@Autowired
IUserService userService;
@Test
public void abcLogin(){
UserDetails ud=userService.getUserDetails("tc2");
System.out.println(ud);
}
步骤4:
UserDetailsServiceImpl类中来调用刚刚编写的UserServiceImpl类中的方法
返回UserDetails对象即可
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
// Spring-Security认证信息时
// 会将用户名传递到这个方法中
// 根据这个用户名获得数据库中加密的密码,
// 如果匹配则登录成功
@Autowired
private IUserService userService;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
return userService.getUserDetails(username);
}
}
8.4 控制授权范围
网站有些页面需要登录后才能访问,但是有些直接就可以访问
我们设置一下授权范围,无论是否登录都可以访问首页
代码如下
//@Configuration表示当前类是配置类,可能向Spring容器中注入对象
@Configuration
//下面的注解表示通知Spring-Security开启权限管理功能
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends
WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService);
}
//控制授权代码在这里!!!!!
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()//对当前全部请求进行授权
.antMatchers(
"/index.html",
"/img/*",
"/js/*",
"/css/*",
"/bower_components/**"
)//设置路径
.permitAll()//允许全部请求访问上面定义的路径
//其它路径需要全部进行表单登录验证
.anyRequest().authenticated().and().formLogin();
}
// 下面需要ProjectDay03
附件
1.仓库地址:https://gitee.com/Blue_Pepsi_Cola/straw