前后端分离系列 -- SpringBoot + Spring Security + Vue 实现用户认证 SpringSecurity如此简单

前后端分离系列 -- SpringBoot + Spring Security + Vue 实现用户认证 SpringSecurity如此简单,第1张

前后端分离系列 -- SpringBoot + Spring Security + Vue 实现用户认证 SpringSecurity如此简单

目录

引言博文系列项目简介效果图开发环境数据表结构项目结构

后端结构前端结构 项目难点

后端难点前端难点 核心源码

前端源码配置登录页路由后端源码 下载链接博主寄语

引言

Hello,我是Bug终结者,一名热爱后端Java的风趣且幽默的程序员~ 终于等到幸运的你~

快来发现我的宇宙哦~

博文系列

 深入浅出前后端分离系列第一篇 :前后端分离 — 深入浅出Spring Boot + Vue实现员工管理系统 Vue如此简单~

 深入浅出前后端分离系列第二篇 :前后端分离 – 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~

 深入浅出前后端分离系列第三篇 :前后端分离 – 深入浅出 Spring Boot + Vue 实现工程项目进度管理系统 Vue不过如此~

项目简介

基于SpringBoot + Vue 实现后端分离项目,具体项目功能要求:

登录、注销、防跳墙功能

要求采用Spring Security安全框架完成

效果图

开发环境

后端:Spring Boot + MyBatis + Maven

前端:Vue + ElementUI

工具:前端使用VSCode,后端使用IDEA

放松时间~

温馨提示:小看怡情,大看伤身

数据表结构

t_user用户表

CREATE TABLE `t_user` (
  `noid` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '账户名',
  `password` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '账户密码',
  `realname` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '真实姓名',
  `role` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL, commit '用户角色'
  PRIMARY KEY (`noid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
项目结构 后端结构

前端结构

项目难点 后端难点

项目结构介绍

UserInfo,用户实体类,主要用于用户登录

SecretConfig:Spring Security核心配置类,该类中配置了用户的认证

CustoUserDetailsService:用户业务类,该类实现UserDetailsService类,主要用于查询数据库中是否存在输入的用户名并返回

Spring Security 安全框架

SecretConfig核心配置类:

package com.wanshi.config;

import com.wanshi.bean.ResultBean;
import com.wanshi.secret.CustomUserDetailsService;
import com.wanshi.utils.PbJsonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.expressionUrlAuthorizationConfigurer;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.web.cors.CorsUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecretConfig extends WebSecurityConfigurerAdapter {

    //注入用户业务类,主要用于查询数据库中是否存在用户信息
    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
    }

    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //配置/api/login_local 
     

    $bg: #283443; 
    $light_gray: #fff; 
    $cursor: #fff; 

    @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { 
      .login-container .el-input input { 
        color: $cursor; 
      } 
    } 

     
    .login-container { 
      .box-change-locale-lang { 
        display: flex; 
        justify-content: flex-end; 
        padding: 20px 30px 0px; 
      } 

      .el-input { 
        display: inline-block; 
        height: 47px; 
        width: 85%; 

        input { 
          background: transparent; 
          border: 0px; 
          -webkit-appearance: none; 
          border-radius: 0px; 
          padding: 12px 5px 12px 15px; 
          color: $light_gray; 
          height: 47px; 
          caret-color: $cursor; 

          &:-webkit-autofill { 
            box-shadow: 0 0 0px 1000px $bg inset !important; 
            -webkit-text-fill-color: $cursor !important; 
          } 
        } 
      } 

    } 
   

   
    $bg: #2d3a4b; 
    $dark_gray: #889aa4; 
    $light_gray: #eee; 

    .login-container { 
      min-height: 100%; 
      width: 100%; 
      background-color: $bg; 
      overflow: hidden; 

      .login-form { 
        position: relative; 
        width: 520px; 
        max-width: 100%; 
        padding: 160px 35px 0; 
        margin: 0 auto; 
        overflow: hidden; 
      } 

      .el-form-item { 
        border: 1px solid rgba(255, 255, 255, 0.1); 
        background: rgba(0, 0, 0, 0.1); 
        border-radius: 5px; 
        color: #454545; 
        padding-left:10px; 
        padding-right: 10px; 

        &.box-remember-pwd { 
          border: none; 
          background-color: rgba(0, 0, 0, 0); 

          .txt-remember-pwd { 
            padding-left: 30px; 
            color: #ffffff; 
          } 
        } 

      } 

      .tips { 
        font-size: 14px; 
        color: #fff; 
        margin-bottom: 10px; 

        span { 
          &:first-of-type { 
            margin-right: 16px; 
          } 
        } 
      } 

      .svg-container { 
        padding: 6px 5px 6px 15px; 
        color: $dark_gray; 
        vertical-align: middle; 
        width: 30px; 
        display: inline-block; 
      } 

      .icon1 { 
        font-size: 18px; 
        color: #eeeeee; 
      } 

      .title-container { 
        position: relative; 

        .title { 
          font-size: 26px; 
          color: $light_gray; 
          margin: 0px auto 40px auto; 
          text-align: center; 
          font-weight: bold; 
        } 

        @media only screen and (max-width: 470px) {
          .title { 
            font-size: 22px;
      }

    }
  }

  .show-pwd {
    position: absolute;
   right: 4px;
    top: 3px;
   cursor: pointer;
    user-select: none;
 }

   .thirdparty-button {
 position: absolute;
right: 0;
 bottom: 6px;
 }

 @media only screen and (max-width: 470px) {
  .thirdparty-button {
  display: none;
}
}
}


Index.vue







  .box-main2{
    display: flex;
    .box-left1{
      width: 420px;
      padding:6px;

    }
    .box-right1{
      flex: 7;
      padding:10px;
      .box-right1-in{
        display: flex;
        flex-direction: column;

        .box-search{
          display: flex;
          padding:10px;
        }

      }
    }
  }





配置登录页路由
{
   path: '/login-local',
   meta: {pageTitle: '本地登录', leftMenuIndex: 'login-local'},
   component: () => import('@/views/LoginLocal')
},
后端源码

CustomUserDetailsService.java

package com.wanshi.secret;

import com.wanshi.bean.UserInfo;
import com.wanshi.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

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

@Component
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo param = new UserInfo();
        param.setUsername(username);
        UserInfo userInfo = userMapper.get(param);
        if (userInfo == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        // 得到用户角色
        String role = userInfo.getRole();

        // 角色集合
        List authorities = new ArrayList<>();
        // 角色必须以`ROLE_`开头,数据库中没有,则在这里加
        authorities.add(new SimpleGrantedAuthority("ROLE_" + role));

        return new User(
                userInfo.getUsername(),
                // 因为数据库是明文,所以这里需加密密码
                new BCryptPasswordEncoder().encode(userInfo.getPassword()),
                authorities
        );
    }
}

下载链接

本项目上传至GitEE码云进行项目管理,具体链接如下:

项目源码:前后端分离项目 – SpringBoot+SpringSecurity + Vue + ElementUI实现用户认证

建议使用SSH秘钥爬取源码

前端配置教程:使用GitEE拉取前端项目并配置,保证运行成功哦~



博主寄语

该项目是一个基于SpringBoot+SpringSecurity + Vue + ElementUI实现用户认证实现的用户认证,项目逻辑稍微复杂,但只要你细心,坚持的敲上几遍,相信你的编程能力会极大的提升,加油~

若在本项目中遇到技术难题,可在下方评论区留言或私信我,授人以鱼不如授人以渔

如果你觉得博主写的不错的话,不妨给个一键三连,点击下方小拳头即可一键三连。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5712150.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存