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

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

开发者学堂课程【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

相关文章
|
26天前
|
关系型数据库 分布式数据库 数据库
成都晨云信息技术完成阿里云PolarDB数据库产品生态集成认证
近日,成都晨云信息技术有限责任公司(以下简称晨云信息)与阿里云PolarDB PostgreSQL版数据库产品展开产品集成认证。测试结果表明,晨云信息旗下晨云-站群管理系统(V1.0)与阿里云以下产品:开源云原生数据库PolarDB PostgreSQL版(V11),完全满足产品兼容认证要求,兼容性良好,系统运行稳定。
|
30天前
|
存储 Oracle 关系型数据库
Dataphin常见问题之想要周期执行任务如何解决
Dataphin是阿里云提供的一站式数据处理服务,旨在帮助企业构建一体化的智能数据处理平台。Dataphin整合了数据建模、数据处理、数据开发、数据服务等多个功能,支持企业更高效地进行数据治理和分析。
|
1月前
|
SQL 开发框架 JavaScript
在 Vue 中进行数据持久化时,有哪些常用的数据库框架?
在 Vue 中进行数据持久化时,有哪些常用的数据库框架?
49 3
|
1月前
|
存储 数据管理 数据处理
数据之光:探索数据库技术的演进之路
数据之光:探索数据库技术的演进之路
60 1
|
1月前
|
存储 运维 关系型数据库
数据的力量:构筑现代大型网站之数据库基础与应用
数据的力量:构筑现代大型网站之数据库基础与应用
49 0
|
1月前
|
SQL Java 数据库连接
从来没想到我们会扒拉nohup文件去找我们想要的数据,然后往数据库中添加。。。...
从来没想到我们会扒拉nohup文件去找我们想要的数据,然后往数据库中添加。。。...
17 0
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL 数据库】2、MySQL 的数据控制语言、函数和约束
【MySQL 数据库】2、MySQL 的数据控制语言、函数和约束
29 0
|
1月前
|
NoSQL Java 数据库连接
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
使用Java实现从数据库查出数据存入Redis,并在查询时先查Redis,如果Redis中没有数据再从数据库中读取
355 1
|
6天前
|
存储 关系型数据库 MySQL
如何处理爬取到的数据,例如存储到数据库或文件中?
处理爬取的数据,可存储为txt、csv(适合表格数据)或json(适合结构化数据)文件。若需存储大量数据并执行复杂查询,可选择关系型(如MySQL)或非关系型(如MongoDB)数据库。以MySQL为例,需安装数据库和Python的pymysql库,创建数据库和表,然后编写Python代码进行数据操作。选择存储方式应考虑数据类型、数量及后续处理需求。
14 1
|
7天前
|
SQL 关系型数据库 MySQL
关系型数据库插入数据的语句
使用SQL的`INSERT INTO`语句向关系型数据库的`students`表插入数据。例如,插入一个`id`为1,`name`为&#39;张三&#39;,`age`为20的记录:`INSERT INTO students (id, name, age) VALUES (1, &#39;张三&#39;, 20)。如果`id`自增,则可简化为`INSERT INTO students (name, age) VALUES (&#39;张三&#39;, 20)`。
6 2

热门文章

最新文章