SpringSecurity从数据库中获取用户信息进行验证的案例详解
作者:BLUcoding 发布时间:2024-01-23 17:16:25
标签:SpringSecurity,数据库,验证
基于 SpringBoot与SpringSecurity整合 案例的修改:
数据库 user 表
注,密码是由 BCrypt 算法加密对应用户名所得。
root$2a$10$uzHVooZlCWBkaGScKnpha.ZrK31NI89flKkSuTcKYjdc5ihTPtPyq
blu$2a$10$mI0TRIcNF4mg34JmH6T1KeystzTWDzWFNL5LQmmlz.fHndcwYHZGe
kaka$2a$10$/GMSSJ3AzeeBK3rBC4t8BOZ5zkfb38IlwlQl.6mYTEpf22r/cCZ1a
admin$2a$10$FKf/V.0WdHnTNWHDTtPLJe2gBxTI6TBVyFjloXG9IuH4tjebOTqcS
数据库 role 表
注:role名称必须带上前缀 ROLE_ (SpringSecurity框架要求)
role_user 表
实体类 SysUser
@Data
public class SysUser {
private Integer id;
private String name;
private String password;
}
实体类 SysRole
@Data
public class SysRole {
private Integer id;
private String name;
}
UserMapper
public interface UserMapper {
@Select("select * from user where name = #{name}")
SysUser loadUserByUsername(String name);
}
RoleMapper
public interface RoleMapper {
@Select("SELECT role.`name` FROM role WHERE role.id in (SELECT role_id FROM "
+ " role_user as r_s JOIN `user` as u ON r_s.user_id = u.id and u.id = #{id})")
List<SysRole> findRoleByUserId(int id);
}
UserService 接口
该接口需继承UserDetailsService
package com.blu.service;
import org.springframework.security.core.userdetails.UserDetailsService;
public interface UserService extends UserDetailsService {
}
UserServiceImpl 实现类
package com.blu.service.impl;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.blu.entity.SysRole;
import com.blu.entity.SysUser;
import com.blu.mapper.LoginMapper;
import com.blu.mapper.UserMapper;
import com.blu.service.UserService;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RoleMapper roleMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
try {
SysUser sysUser = userMapper.loadUserByUsername(username);
if(sysUser==null) {
return null;
}
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
List<SysRole> list = roleMapper.findRoleByUserId(sysUser.getId());
for(SysRole role : list) {
authorities.add(new SimpleGrantedAuthority(role.getName()));
}
//封装 SpringSecurity 需要的UserDetails 对象并返回
UserDetails userDetails = new User(sysUser.getName(),sysUser.getPassword(),authorities);
return userDetails;
} catch (Exception e) {
e.printStackTrace();
//返回null即表示认证失败
return null;
}
}
}
加密类
@Bean
public BCryptPasswordEncoder bcryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
SpringSecurity 配置类
package com.blu.config;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.blu.service.impl.UserServiceImpl;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private UserServiceImpl userServiceImpl;
@Autowired
private BCryptPasswordEncoder bcryptPasswordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2")
.antMatchers("/level3/**").hasRole("vip3");
http.formLogin().loginPage("/tologin")
.usernameParameter("name")
.passwordParameter("password")
.loginProcessingUrl("/login");
http.csrf().disable();
http.logout().logoutSuccessUrl("/");
http.rememberMe().rememberMeParameter("remember");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userServiceImpl).passwordEncoder(bcryptPasswordEncoder);
}
}
以上方式在认证时是将数据库中查出的用户信息通过 UserServiceImpl 封装成 UserDetails 交给 SpringSecurity去认证的,我们还可以让用户实体类直接实现UserDetails:
MyUser:
package com.blu.entity;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class MyUser implements UserDetails {
@Data
private Integer id;
private String name;
private String password;
private List<MyRole> roles;
@JsonIgnore
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles;
}
@Override
public String getPassword() {
return password;
}
@JsonIgnore
@Override
public String getUsername() {
return name;
}
@JsonIgnore
@Override
public boolean isAccountNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isAccountNonLocked() {
return true;
}
@JsonIgnore
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@JsonIgnore
@Override
public boolean isEnabled() {
return true;
}
}
MyRole:
package com.blu.entity;
import org.springframework.security.core.GrantedAuthority;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Data
public class MyRole implements GrantedAuthority {
private Integer id;
private String name;
@JsonIgnore
@Override
public String getAuthority() {
return name;
}
}
MyUserMapper:
package com.blu.mapper;
import com.blu.entity.MyUser;
public interface MyUserMapper {
MyUser findByName(String name);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.blu.mapper.MyUserMapper">
<resultMap type="com.blu.entity.MyUser" id="myUserMap">
<id column="uid" property="id"></id>
<result column="uname" property="name"></result>
<result column="password" property="password"></result>
<collection property="roles" ofType="com.blu.entity.MyRole">
<id column="rid" property="id" />
<result column="rname" property="name" />
</collection>
</resultMap>
<select id="findByName" parameterType="String"
resultMap="myUserMap">
select u.id uid,u.name uname,u.password,r.id rid,r.name rname
from user u,role r,role_user ur
where u.name = #{name} and ur.user_id = u.id and ur.role_id = r.id
</select>
</mapper>
修改:UserServiceImpl:
package com.blu.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.blu.entity.MyUser;
import com.blu.mapper.MyUserMapper;
import com.blu.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private MyUserMapper myUserMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
MyUser myUser = myUserMapper.findByName(username);
return myUser;
}
}
来源:https://blucoding.blog.csdn.net/article/details/110727891


猜你喜欢
- 网上大部分都是上传文件,于是个人参照网上一些博客的内容,写了一个把windows上目录上传到远程linux的一个小程序。下面是代码:clas
- 一、Mysql分区类型1、RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。2、HASH分区:基于用户定义的表达式的返回值
- 由于是上线的项目且已经按照数据逻辑去渲染了能看懂的看逻辑吧。有点多效果如图<template> <div class=&q
- pytorch 库pytorch 本身具有载入cifar10等数据集的函数,但是载入的是3*200*200的张量,当碰到要使用灰度图像时,可
- 以下是演示**“如何在Python中复制文件”的九种方法**。shutil copyfile()方法shutil copy()方法shuti
- 在mysql数据库中,当我们需要模糊查询的时候 ,我们会使用到通配符。首先我们来了解一下2个概念,一个是操作符,一个是通配符。操作符like
- 本文实例为大家分享了python绘制彩虹图的具体代码,供大家参考,具体内容如下from turtle import *#控制彩虹路径def
- 结合网上解决方法,总结了一 * 意三点:1.文件名或路径名开头如果会引起转义,则\要替换为\\2.文件不能放在桌面,因为读取时按中文路径3.运
- 这篇文章主要介绍了python 数据生成excel导出(xlwt,wlsxwrite)代码实例,文中通过示例代码介绍的非常详细,对大家的学习
- 1. 基本环境安装 anaconda 环境, 由于国内登陆不了他的官网 https://www.continuum.io/downloads
- 本文详细介绍了asp中如何使用sql语句删除数据库中的记录,初学asp者来看看!1,首先要明确删除哪条记录无非还就是SQL语句了,比如对应到
- 目录【Python压缩文件夹】导入“zipfile”模块【python压缩文件】导入“zipfile”模块补充zipfile是python里
- 前言Python可以操作Excel的模块不止一种,我习惯使用的写入模块是xlwt(一般都是读写模块分开的)python中使用xlwt操作ex
- SQL Server 2019 Enterprise (x64) - DVD (Chinese-Simplified)企业版ed2k://|
- 本文实例讲述了Python框架Flask的基本数据库操作方法。分享给大家供大家参考,具体如下:数据库操作在web开发中扮演着一个很重要的角色
- 一、什么是系统调用In computing, a system call is the programmatic way in which
- 问题描述由于画图时plt.title()默认是显示英文,如果我们设置标题为中文,会无法显示,如图:plt.title('训练损失
- 前天在生产环境中遇到一个问题:使用 GROUP_CONCAT 函数select出来的数据被截断了,最长长度不超过1024字节,开始还以为是n
- python可以在处理各种数据时,如果可以将这些数据,利用图表将其可视化,这样在分析处理起来,将更加直观、清晰,以下是 利用 PyEchar
- 下面的例子简单的演示了DOM对XML的操作,详细解释请看代码中的注释 <? /****************************