集中式整合之使用数据库数据实现认证|学习笔记

简介: 快速学习集中式整合之使用数据库数据实现认证

开发者学堂课程【Spring Security知识精讲与实战演示(三)集中式整合之使用数据库数据实现认证】学习笔记与课程紧密联系,让用户快速学习知识

课程地址https://developer.aliyun.com/learning/course/732/detail/13064


集中式整合之使用数据库数据实现认证

 

内容介绍:

一、提供对象

二、接口

三、提供用户对象和角色对象

四、指定关系

五、业务逻辑的编写

六、测试

 

一、提供对象

前面已经在整合的环境中加入了通用mapper的环境,接下里将使用通用mapper来完成spring security的认证业务。

首先需要提供一个用户对象sysuser,此类方法的不同之处是将让user的对象直接实现user.details的接口。

接下里讲述里面按所使用的方法。Spring security内部只识别内部为user details的用户对象,并不识别用户自己定义的对象。此时需要用户自己定义的对象直接实现接口,那么以后spring security能够自动识别用户自己定义的对象。也可以先让用户定义的对象不与spring security产生关系,创建完成后,在手动完成该对象。

importorg. springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

public class SysUser implements UserDetails(

@0verride I

public Collection<? extends GrantedAuthority> getAuthorities() (return null;

)

@0verride

public String getPassword() (

return null;

集中式项 )

@0verride

public String getUsername() (

return null;

)

用户除了实现spring security规定的一些方法之外,还需要加入一些自定义的属性。

image.png

在数据库中,打开user,里面的id、username、password和status都属于自定义的属性,一一进行编写。

 

二、接口

首先引进一个integer类型的id,再编写一个string类型的username,保证属性名一致,紧接着编写一个string类型的password,最后还有一个integer类型的status,在里面还需要生成一个integer get的一个方法。

package com.itheima.domain;

Importorg.springframework.security.

core.GrantedAuthority; import

org. springframework. security. core.userdetails.UserDetails;

inport java.util.Collection;

public class SysUser implements UserDetails(

private Integer id;

private String username;

private String password;

private Integer status;I

public Integer getId()

return id;

public void setId(Integer id) (

this.id = id;

)

实现完接口之后,有许多需要重写的方法,下图中四个Boolean值,都是在指定当前用户是否可用。例如最底下的Boolean如果为false,则说明当前用户不可用,则可以将其改为true,上面几个同理改为true,那么就可以不再判断当前用户的状态,在里面的段相当于直接废弃掉。

Averride

public boolean isAccountNonExpired() return true

QOverride

public boolean isAccountNonLocked()( return true;

@0verride

public boolean isCredentialsNonExpired() (return true;

@0verride

public boolean isEnabled()

return true;

)

数据库需要定义,1是开启,0是关闭,当前类型为int类型,不能直接返回,如果是teger int,就可以直接将字符段返回,默认1为true,0为false

继续往上看会发现一个get方法,在里面需要得到当前角色信息,因为当前还没有角色对象,只能先空着这一步。Password直接返回password即可,username直接返回username。此时对象初步完成。

public void setId(Integer id)(

this.id = id;

public voidsetUsername(String username) (

this.username = username;

)

public voidsetPassword(String password) (

this.password = password;

I

public Integer getStatus() (

return status;

public voidsetStatus(Integer status) (

this.status = status;

)

 

三、提供用户对象和角色对象

此时初步完成步骤,还差一步角色信息,这里需要提供一个sysrole对象,可以效仿用户对象的做法,使其直接实现spring security规定的对象,将所需要的类型复制过来,将需要实现的方法实现,此处即一个get方法需要指定。

查看一下需要自定义的属性有哪些,打开角色表,发现有三个属性,ID、rolename和roledesc。

image.png

将其一一进行编写,写入一个integer类型的ID,一个string类型的rolename和string类型的roledesc,里面需要生成一个get方法,最后需要注意的是需要返回一个角色名称即rolename,用户对象有了之后,就可以在用户对象中添加集合属性:list<sysrole>roles,此处同样需要生成一个set get方法。生成完之后,就可以返回给role,到此这俩个对象差不多定义完成。

import java.util.Collection;

import java.util.List;

public class SysUser implements UserDetails (

private Integer id;

private String username;

private String password;

private Integer status;

private List<SysRole> rolgs;

public List<SysRole> getRoles()

return roles;

public void setRoles(List<SysRole> roles) (this.roles = roles;

public Integer getId() (

在此处需要注意的是,当前俩个对象,未来可能会转换成字符串或同间隔的字符串。如果涉及到这些操作的话,那么需要将重写的属性忽略掉。

操作如下:加上jason ignore注解说明,则证明get方法后面的字符串的属性就不再参与字符串的转换了。这一步需要加上,因为这并不属于当前对象的属性,而是规范的方法。同样,这些对象也需要加到user的对象中,需要进行重写。以及Boolean值都需要进行添加,这里的username和password虽然是重写值,但是不需要进行添加,因为自身也有username和password的属性。

return status;

public void setStatus(Integer status) (

this.status = status;

@0verride

public Collection<?extends GrantedAuthority> getAuthorities() (return roles;

@Override

public String getPassword(O (

return password;

@0verride

public String getUsername() (

return username;

到此步为止,重写的方法都已经忽略掉,用户对象和角色对象才算彻底完成。编写完成之后,需要编写对应的itheima mapper映射,在里面需要写入俩个接口:usermapper和角色mapper。在通用mapper中,这俩个接口都继承一个接口。在用户里面同样需要继承一个mapper,里面依然需要一个sysuser,可以提前写入一个提前可以查询的用户名方法: public sysuser findbyname(),可以使用插麦,也可以使用注解。在里面需要传入一个string类型的username。

接着需要加上select的注解:(select * from sys_user where username = #{})。需要注意的是用数据库查询的select * from sys _user,只是当前用户对象的属性但是当前需要分装的是需要角色,因此需要继续往下写:@Results(

@Result(id = true, property ="id", column ="id"),

接下来继续分装role的属性里面的 @Result(property ="roles”, column ,通过当前结果的某列来间接查询出角色对象ID,最终可以在里面指定需要分装的类型。例如想要分装list类型,即写入Javatype = list.class,

import org.apache.ibatis.annotations.Result;

import org.apache.ibatis.annotations.Results;

import org.apache.ibatis.annotations.Select;

inport tk.mybatis. mapper.common. Mapper;

import java.util.List;

public interface UserMapper extends Mapper<SysUser>[

@Select("select *from sys_user where username =#(username)")

@Results(

@Result(id = true, property ="id", column ="id"),

@Result(property ="roles”, column =【id", javaType = List.class, many =Many(select=""))

])

public SysUser findByName(String username);

 

四、指定关系

接下来指定是一对一的关系还是一对多的关系,list是一对多的关系,指定一条嵌套查询的语句,即拿ID当条件查询出list的集合出来。

回到角色里面,需要再指定一个接口,public最终的返回值。写一个integer类型的ID,返回值为一个角色集合,所以在sysrole里面查询,如果只是在一张表中,加不了用户ID,因为在一张表中,没有用户ID。需要连查sys_user_role ur,让这俩张表产生关系。

image.png

1 SELECT ★ FROM sys role r, sys user role ur

2 WHEREr.id=ur.rid AND ur.uid=#(uid)

先看前面一段查询出来的结果,能不能直接分装到结果集中,可以看到sysrole的三个属性与结果集是否一一对应。首先ID是对应的,但是发现rolename和roledesc不一样,一个是下划线,一个是脱汞模式,因此需要改名字使其一致,需要修改ID,修改role name

修改roledesc。

换行之后:

1   SELECTr.id, r.role name roleName, r.role desc roleDesc

2   FROMsys role rrsysuser role ur

3   WHEREr.id=ur.rid AND ur.uid=#(uid)

这时就跟数据库需要分装的对象一致了,将com itheima.mapper.rolemapper.role.findbyuid复制粘贴到用户这边来。到此,mapper的运算文件编写完成。

 

五、业务逻辑的编写

Spring security要求业务逻辑必须是userdetails类型,首先创建一个接口user service,当前接口不能被spring security所识别。因此让自己创建的接口继承user details。继承完毕之后,编写实现类,在基础之上,创建一个impl包,在里面将接口实现。当前的user service对象必须放回到ioc容器中,所以在上面加上service注解。

因为当前是是业务层,可能会用到事务,所以加上事物说明,此处也可省略。

但是今后在里面如果写入大量的增删改查的方法,就需要用到事物的注解。在里面需要注入用户的user mapper。在里面的报错可以忽略掉,因为在注入对象的时候加上一个前面的注解。

此时在着这里加上一个扫描的通用mapper产生的代理对象,代理对象并不是真的有对象,是一个增强对象,因此在检测的时候会认为容器中无此对象。

接下里可以按照需求返回user details对象,这时自己定义的对象就已经是user details类型了,因此此处非常简单,此时会发现业务逻辑会变得特别简单。之前是将俩个对象对换出来变成spring security对象,此时直接让这对象变换成spring security。以上即业务逻辑的过程。

import org.springframework.stereotype.Service;

import

org. springframework.transaction.annotation.Transactional;

@Service

@Transactional

public class UserServiceImpl implements UserService(

@Autowired

private UserMapper userMapper;

@0verride

public

UserDetails

loadUserByUsername(String s) throws UsernamelNotFoundException (

return userMapper.findByName(s);

写完之后还不能直接使用,需要修改配置文件,之前在内存中保存的信息可以删除:auth.user details service (),这是需要一个对象,将user details service 注入进去。

接下里给user details 指定一个加密方式,加密方式在password里面。在此处需要在ioc逻辑中放入一个加密对象。

importorg.springframework. security.crypto.bcrypt.BCryptPasswordEncoder;

C@Configuration

EnableWebSecurity

public

class WebSecurityConfig extends WebSecurityConfigurerAdapter (

@Autowired

private UserService userService;

@Bean

public BCryptPasswordEncoder passwordEncoder()(

return new BCryptPasswordEncoder ();

//指定认证对象的来源

public void configure(AuthenticationManagerBuilder auth) throws Exception( auth.userDetailsService(userService).passwordEncoderQ;

//SpringSecurity配置信息

public void configure(HttpSecurity http) throws Exception (

 

六、测试

到此处可以让spring security自己使用数据库来实现数据认证操作。接下里做一个测试。

测试的时候选择topcat插件的方法测试。在浏览器输入localcost:8080。进入到自定义认证页面,在这里可以用数据库的认证对象。密码登录后,会发现可以访问成功,在里边也可以查看访问产品管理,也能出现。这就证明之前查看这些权限是需要user的角色。当前的用户id是4,它规定的id也为4。就证明user下面是有此角色的,即认证成功。

spring:

mVc:

view:

prefix:/pages/

suffix:.jsp

datasource:

driver-class-name:commysql.jdbc.Driver url:jdbc:mysql:///security_authority username:root

password:root

mybatis:

type-aliases-package:com itheima.domain configuration:

map-underscore-to-camel-case:true logging:

leve1:

com itheima:debug

相关文章
|
2月前
|
存储 人工智能 Cloud Native
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
在9月20日2024云栖大会上,阿里云智能集团副总裁,数据库产品事业部负责人,ACM、CCF、IEEE会士(Fellow)李飞飞发表《从数据到智能:Data+AI驱动的云原生数据库》主题演讲。他表示,数据是生成式AI的核心资产,大模型时代的数据管理系统需具备多模处理和实时分析能力。阿里云瑶池将数据+AI全面融合,构建一站式多模数据管理平台,以数据驱动决策与创新,为用户提供像“搭积木”一样易用、好用、高可用的使用体验。
云栖重磅|从数据到智能:Data+AI驱动的云原生数据库
|
11天前
|
数据采集 数据库 Python
有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
有哪些方法可以验证用户输入数据的格式是否符合数据库的要求?
121 75
|
3月前
|
存储 SQL 关系型数据库
Mysql学习笔记(二):数据库命令行代码总结
这篇文章是关于MySQL数据库命令行操作的总结,包括登录、退出、查看时间与版本、数据库和数据表的基本操作(如创建、删除、查看)、数据的增删改查等。它还涉及了如何通过SQL语句进行条件查询、模糊查询、范围查询和限制查询,以及如何进行表结构的修改。这些内容对于初学者来说非常实用,是学习MySQL数据库管理的基础。
171 6
|
2月前
|
存储 监控 数据处理
flink 向doris 数据库写入数据时出现背压如何排查?
本文介绍了如何确定和解决Flink任务向Doris数据库写入数据时遇到的背压问题。首先通过Flink Web UI和性能指标监控识别背压,然后从Doris数据库性能、网络连接稳定性、Flink任务数据处理逻辑及资源配置等方面排查原因,并通过分析相关日志进一步定位问题。
229 61
|
24天前
|
SQL 存储 运维
从建模到运维:联犀如何完美融入时序数据库 TDengine 实现物联网数据流畅管理
本篇文章是“2024,我想和 TDengine 谈谈”征文活动的三等奖作品。文章从一个具体的业务场景出发,分析了企业在面对海量时序数据时的挑战,并提出了利用 TDengine 高效处理和存储数据的方法,帮助企业解决在数据采集、存储、分析等方面的痛点。通过这篇文章,作者不仅展示了自己对数据处理技术的理解,还进一步阐释了时序数据库在行业中的潜力与应用价值,为读者提供了很多实际的操作思路和技术选型的参考。
40 1
|
28天前
|
存储 Java easyexcel
招行面试:100万级别数据的Excel,如何秒级导入到数据库?
本文由40岁老架构师尼恩撰写,分享了应对招商银行Java后端面试绝命12题的经验。文章详细介绍了如何通过系统化准备,在面试中展示强大的技术实力。针对百万级数据的Excel导入难题,尼恩推荐使用阿里巴巴开源的EasyExcel框架,并结合高性能分片读取、Disruptor队列缓冲和高并发批量写入的架构方案,实现高效的数据处理。此外,文章还提供了完整的代码示例和配置说明,帮助读者快速掌握相关技能。建议读者参考《尼恩Java面试宝典PDF》进行系统化刷题,提升面试竞争力。关注公众号【技术自由圈】可获取更多技术资源和指导。
|
1月前
|
前端开发 JavaScript 数据库
获取数据库中字段的数据作为下拉框选项
获取数据库中字段的数据作为下拉框选项
59 5
|
2月前
|
SQL 关系型数据库 数据库
国产数据实战之docker部署MyWebSQL数据库管理工具
【10月更文挑战第23天】国产数据实战之docker部署MyWebSQL数据库管理工具
234 4
国产数据实战之docker部署MyWebSQL数据库管理工具
|
2月前
|
关系型数据库 MySQL 数据库
GBase 数据库如何像MYSQL一样存放多行数据
GBase 数据库如何像MYSQL一样存放多行数据
|
3月前
|
SQL Ubuntu 关系型数据库
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用
本文为MySQL学习笔记,介绍了数据库的基本概念,包括行、列、主键等,并解释了C/S和B/S架构以及SQL语言的分类。接着,指导如何在Windows和Ubuntu系统上安装MySQL,并提供了启动、停止和重启服务的命令。文章还涵盖了Navicat的使用,包括安装、登录和新建表格等步骤。最后,介绍了MySQL中的数据类型和字段约束,如主键、外键、非空和唯一等。
91 3
Mysql学习笔记(一):数据库详细介绍以及Navicat简单使用