角色登录 - SpringSecurity框架实现用户登录校验角色

我们在企业级开发中, 用户只有在登录了账号才可以对表单中的数据进行相关的操作, 且不同身份角色的用户登录后对数据执行的权限也应该有所不同. 并且这些用户登录的账号不可以自己注册, 需要有权限的管理人员添加用户以及给该用户授予所具备的相关的权限. 下面我们先来实现用户登录后才可以操作数据的功能.

我们还是基于上一篇文章进行编写:https://blog.csdn.net/weixin_42629433/article/details/83342148

一. 在数据库中创建最高权限管理员

-- 用户表
CREATE TABLE users(
id INT(20) NOT NULL AUTO_INCREMENT,	
username VARCHAR(50),
PASSWORD VARCHAR(50),
phoneNum VARCHAR(20),
email VARCHAR(50),
STATUS INT,
PRIMARY KEY (id)		
)

INSERT INTO users VALUES (NULL, 'Zenith', '123456', '153********', '8123*****@qq.com',1);



-- 角色表
CREATE TABLE role(
id INT(20) NOT NULL AUTO_INCREMENT,
roleName VARCHAR(50) ,
roleDesc VARCHAR(50),
PRIMARY KEY (id)		
)

INSERT INTO role VALUES (NULL, 'Manager', '最高权限管理员');



-- 用户角色关联表
CREATE TABLE users_role(
userId VARCHAR(32),
roleId VARCHAR(32)
)

INSERT INTO users_role VALUES ('1', '1');

二. 相关文件配置

1. 导入 SpringSecurity 框架实现功能的相关依赖 :


    org.springframework.security
    spring-security-web
    5.0.1.RELEASE


    org.springframework.security
    spring-security-core
    5.0.1.RELEASE

2. 在 web.xml 中引入 SpringSecurity 框架的配置 :



    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy


    springSecurityFilterChain
    /*

3. 在 resources 下创建 spring-security.xml 文件 :




    
    
    
    
    
    

    
    
        
        
        
        
        
        
        
        
    

    
    
        
            
            
        
    

    
    

4. 在 web.xml 中声明引入 spring-security.xml 文件至核心配置文件



    contextConfigLocation
    classpath:applicationContext.xml, classpath*:spring-security.xml

 

三. 后台代码编写

1. 登录密码加密的工具类 :

package com.cast.domain;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.util.Scanner;

/**
 * 给密码加密的工具类
 */
public class BCryptPasswordEncoderUtils {

    private static BCryptPasswordEncoder bCryptPasswordEncoder=new BCryptPasswordEncoder();

    public static String encodePassword(String password){
        return bCryptPasswordEncoder.encode(password);
    }

    public static void main(String[] args) {
        System.out.println("请输入要加密的密码: ");
        Scanner input = new Scanner(System.in);
        String password = input.nextLine();
        String pwd = encodePassword(password);
        System.out.println("加密后的密码为: ");
        System.out.print(pwd);
    }

}

2. 在 service 层创建一个 IUserService 接口来继承 UserDetailsService 

package com.cast.service;

import org.springframework.security.core.userdetails.UserDetailsService;

public interface IUserService extends UserDetailsService {

}

3. 在 service 层创建一个 UserServiceImpl 类实现 IUserService 接口

package com.cast.service.impl;

import com.cast.dao.IUserDao;
import com.cast.domain.Role;
import com.cast.domain.UserInfo;
import com.cast.service.IUserService;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service("userService")
@Transactional
public class UserServiceImpl implements IUserService {

    @Autowired
    private IUserDao userDao;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo = null;
        try {
            userInfo = userDao.findByUsername(username);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //将自己从数据库中查询到的Users对象封装到UserDetails中
        User user = new User(userInfo.getUsername(), userInfo.getPassword(), userInfo.getStatus() == 0 ? false : true, true, true, true, getAuthority(userInfo.getRoles()));
        return user;
    }

    //定义一个方法 将从数据库中获取到的所有角色装入集合
    public List getAuthority(List roles) {
        List list = new ArrayList();
        for (Role role : roles) {
            list.add(new SimpleGrantedAuthority("ROLE_" + role.getRoleName()));
        }
        return list;
    }

}

4. 在 domain 子工程中声明 users role 的实体封装类 :

package com.cast.domain;

import java.util.List;

/**
 * 与数据库中 users 表对应
 */
public class UserInfo {

    private String id;
    private String username;
    private String password;
    private String phoneNum;
    private String email;
    private int status;
    private String statusStr;
    private List roles;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getStatusStr() {
        return statusStr;
    }

    public void setStatusStr(String statusStr) {
        this.statusStr = statusStr;
    }

    public List getRoles() {
        return roles;
    }

    public void setRoles(List roles) {
        this.roles = roles;
    }

}
package com.cast.domain;

import java.util.List;

/**
 * 与数据库中 role 表对应
 */
public class Role {

    private String id;
    private String roleName;
    private String roleDesc;
    private List permissions;
    private List users;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    public List getPermissions() {
        return permissions;
    }

    public void setPermissions(List permissions) {
        this.permissions = permissions;
    }

    public List getUsers() {
        return users;
    }

    public void setUsers(List users) {
        this.users = users;
    }

}

5. 在 dao 层创建一个 IUserDao 接口

package com.cast.dao;

import com.cast.domain.UserInfo;
import org.apache.ibatis.annotations.*;

/**
 * 登录用户的 dao 层接口
 */
public interface IUserDao {

    //根据用户名查询用户
    @Select("select * from users where username = #{username}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property = "phoneNum", column = "phoneNum"),
            @Result(property = "email", column = "email"),
            @Result(property = "status", column = "status"),
            @Result(property = "roles", column = "id", javaType = java.util.List.class,
                    many = @Many(select = "com.cast.dao.IRoleDao.findByUserId"))
    })
    public UserInfo findByUsername(String username) throws Exception;

}

6. 在 dao 层创建 IRoleDao

package com.cast.dao;

import com.cast.domain.Role;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * 用户的角色的 dao 层接口
 */
public interface IRoleDao {

    //根据用户id查询所有对应角色
    @Select("select * from role where id in (select roleId from users_role where userId = #{userId})")
    public List findByUserId(String userId) throws Exception;
    
}

三. 前台页面核心代码

1. login.jsp 登录界面的 form 表单 :

2. 登录失败后的 failure.jsp 页面提示返回到登录页面的超链接 :

返回到登录页面

 

 

代码下载: https://pan.baidu.com/s/17zb834Qy1P5T3BiV7ivRig

***此代码需在 jdk1.8 下运行使用***

 

你可能感兴趣的:(function)