JavaWeb进阶修炼手册38---spring-security(四)使用数据库中的用户进行验证

1. 前言

通过前面的知识,我们已经能够简单的使用spring-security,并且整合到ssm框架中。当然,前面的例子中我们都是在内存中构造的用户进行验证的,也就是下面这行代码:

<!-- 在内存中构造用户们 -->
<security:authentication-manager>
    <security:authentication-provider>
        <security:user-service>
            <security:user name="user" password="{noop}user" authorities="ROLE_USER"/>
            <security:user name="admin" password="{noop}admin" authorities="ROLE_ADMIN"/>
        </security:user-service>
    </security:authentication-provider>
</security:authentication-manager>

实际的开发过程中,我们都是从数据库中读取的数据,接下来我们介绍如何实现。

2. UserDetails与UserDetailsService

在Spring Security中如果想要使用数据进行认证操作,有很多种操作方式,这里我们介绍使用UserDetails、 UserDetailsService来完成操作。

2.1 UserDetails及其实现类User

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

UserDetails是一个接口,我们可以认为UserDetails作用是于封装当前进行认证的用户信息,相当于之前构造于内存中的用户。但由于其是一个接口,所以我们可以对其进行实现,也可以使用Spring Security内部提供的一个UserDetails的实现类User来完成操作

以下是User类的部分代码:

public class User implements UserDetails, CredentialsContainer {

    private final String username;	//用户登入名
    private String password;	//用户登入密码
    private final Set<GrantedAuthority> authorities;  //用户所基本的权限,比如:ROLE_USER
    private final boolean accountNonExpired;	 	//帐户是否过期    
    private final boolean accountNonLocked; 		//帐户是否锁定
    private final boolean credentialsNonExpired; 	//认证是否过期    
    private final boolean enabled; 					//帐户是否可用

2.2 UserDetailsService

UserDetailsService:

public interface UserDetailsService {        

	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; 
}

UserDetailsService是一个接口,用来让spring-security知道从哪里获取数据库中的用户。由此,spring-security想要知道根据登录名和密码是否有该用户时,会调用UserDetailsService的实现类,事实上之前用的构造于内存中的用户是spring-security对该接口的动态代理实现的。

所以,我们必须编写UserDetailsService的实现类。

3. 使用数据库中的用户进行验证实现步骤

在这里插入图片描述

扫描二维码关注公众号,回复: 11545540 查看本文章

3.1 第一步:编写UserDetailsService的实现类:UserDetailsServiceImpl

package cn.wanghao.springSecurity.service.impl;

import cn.wanghao.springSecurity.dao.UserDao;
import cn.wanghao.springSecurity.domain.SysRole;
import cn.wanghao.springSecurity.domain.SysUser;
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.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = userDao.selectByName(username);
        List<SimpleGrantedAuthority> authorities = this.getAuthority(sysUser.getRoles());
        User user = new User(sysUser.getUserName(), "{noop}" + sysUser.getPassWord(), authorities);
        return user;
    }

    private List<SimpleGrantedAuthority> getAuthority(List<SysRole> roles) {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (SysRole role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
}

注意:上面的 sysUser.getPassWord() 前面加{noop}是因为密码没有加密,明文密码需要加这个。

3.2 第二部:更改spring-security配置文件

再在spring-security中去掉之前构造用户于内存中,该为从我们自定义的UserDetailsServiceImpl类的对象中获取用户:

<!-- 在内存中构造用户们
<security:authentication-manager>
    <security:authentication-provider>
        <security:user-service>
            <security:user name="user" password="{noop}user" authorities="ROLE_USER"/>
            <security:user name="admin" password="{noop}admin" authorities="ROLE_ADMIN"/>
        </security:user-service>
    </security:authentication-provider>
</security:authentication-manager>-->

<!-- 从数据库中获取用户 -->
<security:authentication-manager>
    <security:authentication-provider user-service-ref="userDetailsService">

    </security:authentication-provider>
</security:authentication-manager>

3.3 效果

在这里插入图片描述

3.4 项目源码下载地址

链接:https://pan.baidu.com/s/1Xo1oVjVMvf_eM_9wHKZZqw
提取码:r211

数据库表如下:

sys_user表:

CREATE TABLE `sys_user` (   `id` int(32) NOT NULL
AUTO_INCREMENT,   `userName` varchar(50) CHARACTER SET utf8mb4 COLLATE
utf8mb4_0900_ai_ci NOT NULL,   `passWord` varchar(50) CHARACTER SET
utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,   PRIMARY KEY (`id`) )
ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci

sys_role表:

Create Table

CREATE TABLE `sys_role` (   `id` int(32) NOT NULL AUTO_INCREMENT,  
`name` varchar(50) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB
AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

sys_user_role表:

CREATE TABLE `sys_user_role` (   `user_id` int(32) NOT NULL,  
`role_id` int(32) NOT NULL,   PRIMARY KEY (`user_id`,`role_id`),   KEY
`role_id` (`role_id`),   CONSTRAINT `sys_user_role_ibfk_1` FOREIGN KEY
(`user_id`) REFERENCES `sys_user` (`id`),   CONSTRAINT
`sys_user_role_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `sys_role`
(`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci

猜你喜欢

转载自blog.csdn.net/qq_43546676/article/details/105348436