ssm03 权限管理表结构及登录验证

一、数据库和表结构

1、用户表

用户表信息描述users
在这里插入图片描述
sql语句

CREATE TABLE ssmusers(
id VARCHAR(32) PRIMARY KEY,
email VARCHAR(50) UNIQUE NOT NULL,
username VARCHAR(50),
PASSWORD VARCHAR(50),
phoneNum VARCHAR(20),
STATUS INT
);

DELIMITER $$
CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    TRIGGER `orcl`.`id_ssmusers_trigger` BEFORE INSERT
    ON `orcl`.`ssmusers`
    FOR EACH ROW BEGIN
	SET new.id=REPLACE(UUID(),'-',''); -- 触发器执行的逻辑
    END$$

DELIMITER ;
DELIMITER $$

INSERT INTO ssmusers VALUES('[email protected]','bob','123','12349567890','0')

实体类

/**
 * 与数据库中的users对应
 */
public class UserInfo {
    private String id;
    private String username;
    private String email;
    private String password;
    private String phoneNum;
    private int status;
    private String statusStr;
    private List<Role> roles;
}

2、角色表

角色表信息描述role
在这里插入图片描述
sql语句

CREATE TABLE ssmrole(
	id VARCHAR(32) PRIMARY KEY,
	roleName VARCHAR(50) ,
	roleDesc VARCHAR(50)
);

DELIMITER $$

CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    TRIGGER `orcl`.`id_ssmrole_trigger` BEFORE INSERT
    ON `orcl`.`ssmrole`
    FOR EACH ROW BEGIN
	SET new.id=REPLACE(UUID(),'-',''); -- 触发器执行的逻辑
    END$$

DELIMITER ;

实体类

public class Role {
    private String id;
    private String roleName;
    private String roleDesc;
    private List<Permission> permissions;
    private List<UserInfo> users;
}

3、用户角色表

在这里插入图片描述

用户与角色之间是多对多关系,我们通过user_role表来描述其关联,在实体类中User中存在List,在Role中有List.
而角色与权限之间也存在关系,我们会在后面介绍。
用户与角色关联关系


CREATE TABLE users_role(
	userId VARCHAR(32),
	roleId VARCHAR(32),
	PRIMARY KEY(userId,roleId),
	FOREIGN KEY (userId) REFERENCES ssmusers(id),
	FOREIGN KEY (roleId) REFERENCES ssmrole(id)
);

4、资源权限表

权限资源表描述permission
在这里插入图片描述
sql语句

CREATE TABLE ssmpermission(
	id VARCHAR(32) PRIMARY KEY,
	permissionName VARCHAR(50) ,
	url VARCHAR(50)
);

DELIMITER $$
CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    TRIGGER `orcl`.`id_ssmpermission_trigger` BEFORE INSERT
    ON `orcl`.`ssmpermission`
    FOR EACH ROW BEGIN
	SET new.id=REPLACE(UUID(),'-',''); -- 触发器执行的逻辑
    END$$
DELIMITER ;

实体类

public class Permission {
    private String id;
    private String permissionName;
    private String url;
    private List<Role> roles;
}

5、权限资源与角色关联关系

权限资源与角色是多对多关系,我们使用role_permission表来描述。在实体类Permission中存在List,在Role类中有List

CREATE TABLE role_permission(
	permissionId VARCHAR(32),
	roleId VARCHAR(32),
	PRIMARY KEY(permissionId,roleId),
	FOREIGN KEY (permissionId) REFERENCES ssmpermission(id),
	FOREIGN KEY (roleId) REFERENCES ssmrole(id)
)

INSERT INTO role_permission VALUES('a84dd4b2de0e11eab7b2005056c00001','fd21c1eddddb11eab7b2005056c00001');

二、Spring Security使用数据库认证

在这里插入图片描述

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

1、UserDetails

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 String password;
	private final String username;
	private final Set<GrantedAuthority> authorities;
	private final boolean accountNonExpired; //帐户是否过期
	private final boolean accountNonLocked; //帐户是否锁定
	private final boolean credentialsNonExpired; //认证是否过期
	private final boolean enabled; //帐户是否可用

2、UserDetailsService

public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

上面将UserDetails与UserDetailsService做了一个简单的介绍,那么我们具体如何完成Spring Security的数据库认证操作哪,我们通过用户管理中用户登录来完成Spring Security的认证操作。

三、用户登录配置

1、web.xml配置

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

  <!-- 配置加载类路径的配置文件 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:applicationContext.xml,
      <!--登录验证配置文件-->classpath*:spring-security.xml</param-value>
  </context-param>

  <!-- 配置监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- 前端控制器(加载classpath:springmvc.xml 服务器启动创建servlet) -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 配置初始化参数,创建完DispatcherServlet对象,加载springmvc.xml配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- 服务器启动的时候,让DispatcherServlet对象创建 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>

  <!-- 解决中文乱码过滤器 -->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


  <!--配置登录验证springSecurity-->
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>

</web-app>

2、spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <!-- 配置不拦截的资源 -->
    <security:http pattern="/login.jsp" security="none"/>
    <security:http pattern="/failer.jsp" security="none"/>
    <security:http pattern="/css/**" security="none"/>
    <security:http pattern="/img/**" security="none"/>
    <security:http pattern="/plugins/**" security="none"/>
    <!--配置具体的规则
    	auto-config="true"	不用自己编写登录的页面,框架提供默认登录页面
    	use-expressions="false"	是否使用SPEL表达式(没学习过)-->
    <security:http auto-config="true" use-expressions="false">
        <!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="访问系统的人,必须有ROLE_USER的角色" -->
        <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>

        <!-- 定义跳转的具体的页面 -->
        <!--
            login-page:自定义登陆页面
            login-processing-url:登录的URL
            default-target-url 登陆成功后跳转的页面。

            authentication-failure-url:用户名密码不对
                用户权限校验失败之后才会跳转到这个页面,
                如果数据库中没有这个用户则不会跳转到这个页面。
            default-target-url="/index.jsp":默认目标路径
            authentication-success-forward-url:满足权限,认证成功进入的页面。
            注:登陆页面
                用户名固定 username      密码 password     action:login
         -->
        <security:form-login
                login-page="/login.jsp"
                login-processing-url="/login.do"
                default-target-url="/index.jsp"
                authentication-failure-url="/failer.jsp"
                authentication-success-forward-url="/pages/main.jsp"
        />

        <!-- 关闭跨域请求 -->
        <security:csrf disabled="true"/>
        <!-- 退出 -->
        <security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp" />
    </security:http>


    <!-- 切换成数据库中的用户名和密码 -->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userService">
        </security:authentication-provider>
    </security:authentication-manager>


</beans>

3、service

IUserService

package com.itheima.ssm.service;

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

public interface IUserService extends UserDetailsService {

}

UserServiceImpl

@Transactional
@Service("userService")
public class UserServiceImpl implements IUserService {
    @Autowired
    private IUserDao userDao;
    
    @Override
    public UserDetails loadUserByUsername(String username){
        UserInfo userInfo = null;
        try {
            userInfo = userDao.findByUsername(username);

        } catch (Exception e) {
            e.printStackTrace();
        }
        //处理自己的用户对象封装成UserDetails
        User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),
                userInfo.getStatus()==0?false:true,true,
                true,true,
                getAuthority(userInfo.getRoles()));
        return user;
    }

    //集合中装入
    private List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {
        List<SimpleGrantedAuthority> list = new ArrayList<>();
        for (Role role : roles) {
            list.add(new SimpleGrantedAuthority("ROLE_"+(role.getRoleName()).toUpperCase()));
        }
        return list;
    }

4、Dao

IUserDao

public interface IUserDao {
    @Select("select * from ssmusers where username = #{username}")
    @Results({
            @Result(id = true,property = "id",column = "id"),
            @Result(column = "username",property = "username"),
            @Result(column = "password",property = "password"),
            @Result(column = "email",property = "email"),
            @Result(column = "phoneNum",property = "phoneNum"),
            @Result(column = "status",property = "status"),
            @Result(property = "roles" ,column = "id",javaType = java.util.List.class
            ,many = @Many(select = "com.itheima.ssm.dao.IRolesDao.findByIdRoles"))
    })
    public UserInfo findByUsername(String username) throws Exception;
}

IRolesDao

public interface IRolesDao {
    @Select("select * from ssmrole where id in " +
            "(select roleId from users_role where userId = #{id})")
    List<Role> findByIdRoles(String id);
}

5、页面jsp

login.jsp 登录页面

failer.jsp 登陆失败跳转页面

main.jsp 登陆成功跳转页面

index.jsp 权限不足登陆成功

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<jsp:forward page="/pages/main.jsp"></jsp:forward>
</body>
</html>

四、用户退出

使用spring security完成用户退出,非常简单
配置spring-security.xml

<security:logout invalidate-session="true" 
logout-url="/logout.do" 
logout-successurl="/login.jsp" />

jsp页面注销按钮

<a href="${pageContext.request.contextPath}/logout.do"
class="btn btn-default btn-flat">注销</a>

猜你喜欢

转载自blog.csdn.net/qq_42390340/article/details/108053666
今日推荐