【Spring Security】入门——实现用户注册登录

2023-11-04

Spring Security 是一个功能强大且高度可自定义的身份验证和访问控制框架,它侧重于为 Java 应用程序提供身份验证和授权。
官网传送门:Spring Security官网

本篇文章目的在于快速使用Spring Boot与Spring Security搭建一个项目,实现简单的用户注册登录。

项目已完整上传到GitHub传送门

此项目所用知识点:

  1. Spring Boot
  2. Spring Security
  3. MySQL
  4. Mybatis
  5. JSP

一、项目框架

1. 项目结构

在这里插入图片描述

2. 选择安装依赖

使用Spring Boot进行项目创建。
依赖勾选

  1. Spring Boot DevTools
  2. Spring Web
  3. Spring Security
  4. Mybatis Framework
  5. MySQL Driver

以此pom.xml文件为准

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springboot-security</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 引入springboot -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- spring boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- spring security-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!-- jsp -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- jstl -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <!-- tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <!--用于编译jsp -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.2</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 配置tomcat -->
    <build>
        <finalName>security-springboot</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>

                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <configuration>
                        <encoding>utf-8</encoding>
                        <useDefaultDelimiters>true</useDefaultDelimiters>
                        <resources>
                            <resource>
                                <directory>src/main/resources</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>**/*</include>
                                </includes>
                            </resource>
                            <resource>
                                <directory>src/main/java</directory>
                                <includes>
                                    <include>**/*.xml</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

二、数据库

共5张表

  1. t_user 用户表
  2. t_role 角色表
  3. r_user_role 用户-角色
  4. r_permission 权限表
  5. r_role_permission 角色-权限
/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50610
 Source Host           : localhost:3306
 Source Schema         : user_db

 Target Server Type    : MySQL
 Target Server Version : 50610
 File Encoding         : 65001

 Date: 21/07/2020 21:29:29
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限标识符',
  `description` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
  `url` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', 'p1', '测试资源1', '/resource/r1');
INSERT INTO `t_permission` VALUES ('2', 'p2', '测试资源2', '/resource/r2');
INSERT INTO `t_permission` VALUES ('3', 'p3', '测试资源3', '/resource/r3');

-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role`  (
  `id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `update_time` datetime(0) NULL DEFAULT NULL,
  `status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `unique_role_name`(`role_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', NULL, NULL, NULL, '');

-- ----------------------------
-- Table structure for t_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission`  (
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  PRIMARY KEY (`role_id`, `permission_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` VALUES ('1', '1');
INSERT INTO `t_role_permission` VALUES ('1', '2');

-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `fullname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户姓名',
  `mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'zhangsan', '$2a$10$37vdSYJUVguwXpLDnZfEt.UDC0y6Yk2RCzFuJKfOrWCiTnUFlmj3K', NULL, NULL);

-- ----------------------------
-- Table structure for t_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role`  (
  `user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `create_time` datetime(0) NULL DEFAULT NULL,
  `creator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;

-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES ('1', '1', NULL, NULL);

SET FOREIGN_KEY_CHECKS = 1;

三、代码实现

实现思路

  1. 配置Spring Boot环境。将服务器配置、数据源、MyBatis映射文件、启动文件完成配置。
  2. 完成基本的jsp页面。用于测试用户注册、登录功能。
  3. 配置视图控制器。将项目的根路径重定向到login-view,再将login-view转发到真实的login.jsp页面。
  4. 进行Spring Security配置。主要配置密码编码器和安全拦截器
  5. 编写dao层和mapper文件。用于连接数据库。
  6. 编写service层。一方面是实现用户的注册和登录,另一方面是实现spring-security核心接口,其负载着用户特定数据,它被用来在整个框架作为一个用户DAO。
  7. 编写controller层。用于页面访问,在controller接口中可以设置接口的访问权限,让Spring Security进行安全验证。

1. 配置文件

application.properties

# web
server.port=8080
server.servlet.context-path=/
spring.application.name=security-springboot
spring.mvc.view.prefix=/WEB-INF/view/
spring.mvc.view.suffix=.jsp
# DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/user_db
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml

SpringBootApp.java

package com.aaa;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * springboot启动程序
 * @author 淮南King
 */
@SpringBootApplication
@MapperScan("com.aaa.dao")
public class SpringBootApp {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootApp.class,args);
    }
}

2. 编写测试页面

在这里插入图片描述

login.jsp

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>

<h1>登录</h1>
<form action="/login" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="登录">
</form>
<hr>
<p><a href="/register">注册</a></p>
</body>
</html>

register.jsp

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" %>
<html>
<head>
    <title>用户注册</title>
</head>
<body>
<h1>注册</h1>
<form action="/user/register" method="post">
    用户名:<input type="text" name="username"><br>
    密码:<input type="password" name="password"><br>
    <input type="submit" value="注册">
</form>
<hr>
<p><a href="/">登录</a></p>
</body>
</html>

menu.jsp

<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" %>
<html>
<head>
    <title>菜单页</title>
</head>
<body>
<h1>菜单页</h1>
欢迎${username}登录
<hr>
<h3><a href="/resource/r1" target="_blank">资源一</a></h3>
<h3><a href="/resource/r2" target="_blank">资源二</a></h3>
<h3><a href="/resource/r3" target="_blank">资源三</a></h3>
</body>
</html>

3. 配置视图控制器

WebConfig.java

package com.aaa.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * springmvc配置
 * @author 淮南King
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {
    /**
     * 用此方法来添加视图控制器。
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //将根路径重定向到/login-view
        registry.addViewController("/").setViewName("redirect:/login-view");
        //将login-view转到login页面
        registry.addViewController("/login-view").setViewName("login");
    }
}

4. 进行Spring Security配置。

WebSecurityConfig.java

package com.aaa.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * spring security配置
 *
 * @author 淮南King
 */
@Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig
    extends WebSecurityConfigurerAdapter {

    //密码编码器
    @Bean public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //安全拦截机制
    @Override protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            //所有/r/**的请求必须认证通过
            .antMatchers("/r/**").authenticated()
            //除了/r/**,其它的请求可以访问
            .anyRequest().permitAll()
            .and()
            //允许表单登录
            .formLogin()
            //登录页面路径
            .loginPage("/login-view")
            .loginProcessingUrl("/login")
            //自定义登录成功的页面地址
            .successForwardUrl("/login-success")
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
            .logout()
            //登录退出
            .logoutUrl("/logout")
            .logoutSuccessUrl("/login-view?logout");
    }
}

5. 编写dao层和mapper文件

UserDao.java

package com.aaa.dao;

import com.aaa.entity.UserDto;

import java.util.List;

/**
 * 用户信息持久层
 * @author 淮南King
 */
public interface UserDao {
    /**
     * 根据账号查询用户信息
     *
     * @param username 用户姓名
     * @return 用户信息
     */
    UserDto getUserByUsername(String username);

    /**
     * 根据用户id查询用户权限
     *
     * @param userId 用户id
     * @return 权限列表
     */
    List<String> findPermissionsByUserId(String userId);

    /**
     * 添加用户
     *
     * @param userDTO 用户信息
     * @return 修改条数
     */
    int addUser(UserDto userDTO);
}

UserMapper.xml

注意:mapper文件放置的位置在application.properties中的mybatis.mapper-locations进行路径设置

<?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.aaa.dao.UserDao">

    <select id="getUserByUsername" parameterType="String" resultType="com.aaa.entity.UserDto">
        select id,username,password,fullname,mobile from t_user where username = #{username}
    </select>

    <select id="findPermissionsByUserId" parameterType="String" resultType="String">
        SELECT code FROM t_permission WHERE id IN(
            SELECT permission_id FROM t_role_permission WHERE role_id IN(
            SELECT role_id FROM t_user_role WHERE user_id = #{id} ))
    </select>

    <insert id="addUser" parameterType="com.aaa.entity.UserDto">
        INSERT INTO `user_db`.`t_user`(`username`, `password`) VALUES (#{username},#{password})
    </insert>
</mapper>

6. 编写service层

UserService.java

package com.aaa.service;

import com.aaa.dao.UserDao;
import com.aaa.entity.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 用户信息持久业务层
 *
 * @author 淮南King
 * @date 2020-07-21
 */
@Service
public class UserService {

    @Autowired
    UserDao dao;

    public UserDto getUserByUsername(String username) {
        return dao.getUserByUsername(username);
    }

    public List<String> findPermissionsByUserId(String userId) {
        return dao.findPermissionsByUserId(userId);
    }

    /**
     * 添加用户
     * @param userDTO
     * @return
     */
    public int addUser(UserDto userDTO) {
        //获取密码编码器
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        //将用户的密码进行编码
        String password = passwordEncoder.encode(userDTO.getPassword());
        //将编码后的密码覆盖到用户信息中
        userDTO.setPassword(password.substring(8));
        //将用户信息持久化到数据库中
        return dao.addUser(userDTO);
    }
}

SpringDataUserDetailsService.java
实现spring-security核心接口,其负载的用户特定数据。

package com.aaa.service;

import com.aaa.dao.UserDao;
import com.aaa.entity.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
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.List;

/**
 * 实现spring-security核心接口,其负载的用户特定数据。
 *
 * @author 淮南King
 */
@Service
public class SpringDataUserDetailsService implements UserDetailsService {

    @Autowired
    UserDao userDao;

    // 根据账号查询用户信息
    @Override public UserDetails loadUserByUsername(String username) {
        //将来连接数据库根据账号查询用户信息
        UserDto userDto = userDao.getUserByUsername(username);
        //当查询此用户不存在时,将抛出用户名未找到异常
        if (userDto == null) {
            throw new UsernameNotFoundException("No such user found, the user name is: "+username);
        }
        //根据用户id查询权限
        List<String> permissions = userDao.findPermissionsByUserId(userDto.getId());
        //将permissions转为数组
        String[] permissionArray = new String[permissions.size()];
        permissions.toArray(permissionArray);
        UserDetails userDetails =
            User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray)
                .build();
        return userDetails;
    }
}

7. 编写controller层

LoginController.java
用于登录注册

package com.aaa.controller;

import com.aaa.entity.UserDto;
import com.aaa.service.UserService;
import com.aaa.util.SecurityUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 淮南King
 */
@RestController
public class LoginController {

    @Resource private UserService service;

    @RequestMapping(value = "/login-success",produces = {"text/plain;charset=UTF-8"})
    public ModelAndView loginSuccess(){
        //获取当前线程的SecurityContext
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取当前线程中用户的名称,将名称传递至页面
        Map<String,Object> attributes = new HashMap<>();
        attributes.put("username",SecurityUtil.getUserNameByAuthentication(authentication));
        return new ModelAndView("menu",attributes);
    }

    @PostMapping("/user/register")
    public String register(UserDto userDto) {
        service.addUser(userDto);
        return userDto.getUsername()+"注册成功";
    }
    @GetMapping("/register")
    public ModelAndView registerView() {
        return new ModelAndView("register");
    }

}

AuthController.java
用于资源访问

package com.aaa.controller;

import com.aaa.util.SecurityUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 淮南King
 * @date 2020-07-21
 */
@RestController
@RequestMapping("/resource")
public class AuthController {

    /**
     * 测试资源1
     * 拥有p1权限才可以访问
     *
     * @return
     */
    @GetMapping(value = "/r1", produces = {"text/plain;charset=UTF-8"})
    @PreAuthorize("hasAuthority('p1')")
    public String resource1() {
        //获取当前线程的SecurityContext
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        //获取当前线程的名称
        return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源1";
    }

    /**
     * 测试资源2
     * 拥有p2权限才可以访问
     *
     * @return
     */
    @GetMapping(value = "/r2", produces = {"text/plain;charset=UTF-8"})
    @PreAuthorize("hasAuthority('p2')")
    public String resource2() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源2";
    }

    /**
     * 测试资源3
     * 拥有p3权限才可以访问
     *
     * @return
     */
    @GetMapping(value = "/r3", produces = {"text/plain;charset=UTF-8"})
    @PreAuthorize("hasAuthority('p3')")
    public String resource3() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源3";
    }
}

附:实体类与帮助类

实体类

UserDto.java

package com.aaa.entity;

/**
 * DTO:与数据库保持一致<br>
 * 用户信息
 * @author 淮南King
 */
public class UserDto {
    /**
     * 用户id
     */
    private String id;
    /**
     * 用户名
     */
    private String username;
    /**
     * 用户密码
     */
    private String password;
    /**
     * 用户角色ID
     */
    private Integer roleId;

    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 Integer getRoleId() {
        return roleId;
    }

    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }
}

PermissionDto.java

package com.aaa.entity;
/**
 *  权限信息
 * @author 淮南King
 */
public class PermissionDto {
    /**
     * 权限id
     */
    private String id;
    /**
     * 权限代号
     */
    private String code;
    /**
     * 权限描述
     */
    private String description;
    /**
     * 路径
     */
    private String url;

    public String getId() {
        return id;
    }

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

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
}

帮助类

SecurityUtil.java

package com.aaa.util;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * Security帮助类
 * @author 淮南King
 * @date 2020-07-21
 */
public class SecurityUtil {

    /**
     * 根据当前执行线程的SecurityContext获取用户名称
     * @param authentication 当前认证通过的用户身份
     * @return 用户名
     */
    public static String getUserNameByAuthentication(Authentication authentication){
        String username = null;
        //用户身份
        Object principal = authentication.getPrincipal();
        if(principal == null){
            return "匿名";
        }
        if(principal instanceof UserDetails){
            UserDetails userDetails = (UserDetails)principal;
            username = userDetails.getUsername();
        }else{
            username = principal.toString();
        }
        return username;
    }
}


项目已完整上传到GitHub传送门

end…

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Spring Security】入门——实现用户注册登录 的相关文章

随机推荐

  • LabVIEW必知

    介绍 基础知识 数学函数 矩阵数学 数据采集 介绍 传感器和信号 硬件 采集数据 操作数据采集系统需要软件 而这正是LabVIEW发挥作用的地方 LabVIEW旨在与National Instruments数据采集系统一起使用 在收集数据之
  • 微服务(Microservice)那点事

    WHAT 什么是微服务 微服务简介 这次参加JavaOne2015最大的困难就是听Microservice相关的session 无论内容多么水 只要题目带microservice 必定报不上名 可见Microservice有多火 最喜欢其中
  • VUE3 学习笔记(七)动态样式 class 实现

    目录 一 绑定 HTML class 1 绑定对象 2 绑定数组 3 在组件上使用 二 绑定内联样式 1 绑定对象 2 绑定数组 3 自动前缀 4 样式多值 数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式 因为
  • php GD库做水印功能,合并图片

    1 创建一个适应大小的底层图片 2 读取需要拼接的图片 dst data file get contents dst src dst img imagecreatefromstring dst data 3 把读取的图放到指定的位置 这里需
  • Redis吊打面试官的经典面试题整理

    编程界的小学生 1 Redis为什么是key value的 为什么不是支持SQL的 这题第一眼看到有点懵逼 选择key value的原因 key value简单粗暴 使用方便 效率更佳 为什么不支持sql 因为redis的内存模型是一个ha
  • OSG中的示例程序简介

    1 example osganimate一 演示了路径动画的使用 AnimationPath AnimationPathCallback 路径动画回调可以作用在Camera CameraView MatrixTransform Positi
  • apt-get 自动补全包名

    转自 http blog csdn net seasonkky article details 6321150 现象 bash的一般命令补全正常 apt get install 的包名无法自动补全 解决 实际上 在运行这句后 就可以自动补全
  • Go(六)切片

    目录 引子 切片 切片的定义 切片的长度和容量 切片表达式 使用make 函数构造切片 切片的本质 判断切片是否为空 切片不能直接比较 切片的赋值拷贝 切片遍历 append 方法为切片添加元素 切片的扩容策略 使用copy 函数复制切片
  • onInterceptTouchEvent和onTouchEvent调用关系详解

    一 onTouch onTouch是View中OnTouchListener接口中的方法 处理View及其子类被touch是的事件处理 当然 前提是touch时间能够传递到指定的view Q1 为什么会传递不到呢 Java代码 Interf
  • 供需匹配优化优化算法【matlab】

    一 算法流程 应用背景 共享停车预约系统的构成主体 即车位供给用户 停车用户和运营管理者 并对预约系统的运营模式进行了分析 为本文所构建的模型提供了相应的理论基础 其次 在已知所有预约需求停车信息的前提下 基于介绍的定时型决策预约运营模式
  • 光线追踪渲染实战(四):微平面理论与迪士尼 BRDF,严格遵循物理!

    项目代码仓库 GitHub https github com AKGWSB EzRT gitee https gitee com AKGWSB EzRT 目录 前言 0 前情回顾 1 微平面理论 2 BRDF 介绍 3 迪士尼原则的 BRD
  • python读取excel文件,对内容分类排序,显示每类的前5行

    先读取excel文件 然后再分类显示 创建文件 import pandas as pd data pd read excel path1 path1Excel路径 data1 data groupby by 字段 head 5 print
  • [电动智能汽车-1]:原理 - 纯电动汽车的工作原理

    目录 第1章 纯电动汽车的工作原理 1 1 汽车的演进路线 1 2 传统汽车的简化模型 1 3 纯电动汽车的简化模型 1 4 纯电动汽车的驱动模型 1 5 电动车与燃油车的比较 第2章 纯电动汽车 非智能驾驶 内部工作原理 2 1 逻辑结构
  • 用C语言如何编程一道选择题,使用C语言编写一道简单的编程题

    C语言 是一种通用的 过程式的编程语言 广泛用于系统与应用软件的开发 具有高效 灵活 功能丰富 表达力强和较高的移植性等特点 在程序员中备受青睐 C语言是世界上最流行 使用最广泛的高级程序设计语言之一 今天小编要为大家分享的一篇教程就是 使
  • vue项目background-image引入背景图报错

    之前写好的代码明明运行很正常 今天早上突然在预发环境挂掉了 31mERROR in node modules extract text webpack plugin dist loader js omit 1 remove true nod
  • UE4 UPROPERTY属性修饰符用bool变量控制变量是否可编辑

    meta EditCondition bool变量 UPROPERTY EditAnyWhere BlueprintReadWrite Category UPROPERTY Test bool A UPROPERTY EditAnyWher
  • 【Angular2】模板语法之 ngModel

    NgModel实现双向绑定及其实现原理 讨论 ngModel 之前 先讲下属性绑定和事件绑定 在属性绑定中 值从模型中流动到视图上的目标属性 通过把属性名放在方括号中来标记出目标属性 这是从模型到视图的单向数据绑定 在事件绑定中 值从视图上
  • 51单片机学习笔记(七) -蜂鸣器

    文章目录 一 蜂鸣器的概念 1 分类 2 工作原理 3 原理图 二 让蜂鸣器响起来 三 用定时器控制蜂鸣器音调 四 蜂鸣器发出滴滴声 总结 一 蜂鸣器的概念 1 分类 1 无源蜂鸣器 必须方波信号驱动才能发声 2 有缘蜂鸣器 给高电平驱动即
  • VMware虚拟机网络连接设置——仅主机模式(Windows版)

    VMware虚拟机网络连接设置 仅主机模式 Windows版 前言 各位看官 小二已多次测试教程的实用性及准确性 请按目录顺序放心食用 一 设置VMware的虚拟网络 1 1 打开虚拟网络编辑器 在VMware软件窗口工具栏选择 编辑 gt
  • 【Spring Security】入门——实现用户注册登录

    一 项目框架 1 项目结构 2 选择安装依赖 二 数据库 三 代码实现 实现思路 1 配置文件 2 编写测试页面 login jsp register jsp menu jsp 3 配置视图控制器 4 进行Spring Security配置