精华内容
下载资源
问答
  • Security+
    千次阅读
    2021-05-11 14:19:19

    Security+是针对信息安全基础级从业者的认证,偏重技术实操。无论是毕业生,还是没有经过正统安全教育的小白帽,甚至是信息安全管理岗位的资深人士和非安全岗位的运维及开发人员,Security+都不失为一门优秀的安全技术实操类培训。

    图片

    Security+认证如此火爆的原因?

    原因一:在所有信息安全认证当中,偏重信息安全技术的认证是空白的, Security+认证正好可以弥补信息安全技术领域的空白 。

    目前行业内受认可的信息安全认证主要有CISP和CISSP,但是无论CISP还是CISSP都是偏重信息安全管理的,技术知识讲的宽泛且浅显,考试都是一带而过。而且CISSP要求持证人员的信息安全工作经验都要5年以上,CISP也要求大专学历4年以上工作经验,这些要求无疑把有能力且上进的年轻人的持证之路堵住。在现实社会中,无论是找工作还是升职加薪,或是投标时候报人员,认证都是必不可少的,这给年轻人带来了很多不公平。而Security+的出现可以扫清这些年轻人职业发展中的障碍,由于Security+偏重信息安全技术,所以对工作经验没有特别的要求。只要你有IT相关背景,追求进步就可以学习和考试。

    原因二:IT运维人员工作与翻身的利器。

    在银行、证券、保险、信息通讯等行业,IT运维人员非常多,IT运维涉及的工作面也非常广。是一个集网络、系统、安全、应用架构、存储为一体的综合性技术岗。虽然没有程序猿们“生当做光棍,死亦写代码”的悲壮,但也有着“锄禾日当午,不如运维苦“的感慨。天天对着电脑和机器,时间长了难免有对于职业发展的迷茫和困惑。Security+国际认证的出现可以让有追求的IT运维人员学习网络安全知识,掌握网络安全实践。职业发展朝着网络安全的方向发展,解决国内信息安全人才的匮乏问题。另外,即使不转型,要做好运维工作,学习安全知识取得安全认证也是必不可少的。

    原因三:接地气、国际范儿、考试方便、费用适中!

    CompTIA作为全球ICT领域最具影响力的全球领先机构,在信息安全人才认证方面是专业、公平、公正的。Security+认证偏重操作且和一线工程师的日常工作息息相关。适合银行、证券、保险、互联网公司等IT相关人员学习。作为国际认证在全球147个国家受到广泛的认可。

    在目前的信息安全大潮之下,人才是信息安全发展的关键。而目前国内的信息安全人才是非常匮乏的,相信Security+认证一定会成为最火爆的信息安全认证。

    报名Security+直播培训,您将获得:
    1、赠送Security+录播视频、模拟题解析课程视频;
    2、奖学金1000元京东卡:开班起3个月内,考试分数>800分,前10人获得奖学金;
    3、赠送教材三本:官方图书、课程讲义、绝密题库(电子);
    4、赠送ITIL V3、ITIL实务、ISO27001等在线视频课程;

    想要了解Security+认证更多情况及课程大纲,可以填写下方表单

    https://www.jsform.com/web/formview/5f0673c975a03c5c8dd596d6

    更多相关内容
  • SpringBoot2+MybatisPlus+SpringSecurity+jwt+redis+Vue人事管理系统源码,人事管理系统是基于当前流行技术组合的前后端分离:SpringBoot2+MybatisPlus+SpringSecurity+jwt+redis+Vue。 系统分为十一大模块:首页、...
  • Q1 :A security administrator wants to implement strong security on the company smart phones and terminal servers located in the data center. Drag and drop the applicable controls to each asset types? ...
  • security+拖图题答案.pdf

    2021-08-05 16:27:48
    security+拖图题答案.pdf
  • SpringBoot+SpringSecurity+JWT+MybatisPlus实现基于注解的权限验证,可根据注解的格式不同,做到角色权限控制,角色加资源权限控制等,粒度比较细化。 @PreAuthorize("hasAnyRole('ADMIN','USER')"):具有admin或...
  • CompTIA Security+ SY0-601 PDF V21.75,考過PASS 應該與當時題目差不多,希望有幫到你們
  • professor-messer-comptia-sy0-401-security-plus-study-guide-v5
  • 课程概述该互联网实战项目是基于 Spring Boot 2+ SpringSecurity5+Element UI+Vue Admin Template+蚂蚁可视化AntV 等技术栈开发的项目,采用分布式,多模块,前后端分离开发。包括图形展示、权限管理、用户...
  • Springboot整合Spring security+Oauth2+JWT搭建认证服务器,网关,微服务之间权限认证及授权
  • SpringSecurity5+Element?UI+Vue?Admin?Template+蚂蚁可视化AntV?等技术栈开发的项目,采用分布式,多模块,前后端分离开发。包括图形展示、权限管理、用户管理等功能。【后端技术】技术说明Spring?Boot2MVC框架?...
  • Security+培训全套PPT和知识点分享,供大家学习参考。 1、Security+培训-课程大纲(1) 2、Security+培训-安全基本概念(1.1) 3、Security+培训-网络安全(1.1) 4、Security+培训-合规与运维安全(1.1) 5、Security+培训...
  • 基于vue-cli脚手架以及基于SpringBoot+SpringSecurity+JWT+SpringDataJpa的前后端java 项目
  • springboot+security+cas集成demo。。
  • Spring security+jwt服务鉴权完整代码.实现服务鉴权访问, 携带token访问服务, 缺失或无效都提示401
  • springSecurity+springBoot+jwt springSecurity+springBoot+jwt springSecurity+springBoot+jwt
  • Security+认证学习/备考经验

    千次阅读 2022-03-22 00:00:37
    Security+认证学习资料/备考经验

    一、Security+认证适合哪些人学习

    ”Security+ 认证是一种中立第三方认证,也是全球知名度最高的信息安全认证之一,其考试机构为美国计算机行业协会CompTIA 。Security+是和CISSP、CISA等共同包含在内的国际IT业10大热门认证之一,是美国国防部、美国国务院等10多个国家政府和权威组织指定的信息安全国际认证,并得到了Apple、Dell、HP、IBM、Intel 等众多企业的认可,作为国际认证在全球147个国家和地区受到广泛认可,被全球企业和安全专业人士所普遍采纳。“ 但是在中国区域,由于信息安全法律不同等原因,这个认证的知名度不高。

    经过我一段时间的学习,认为Security+十分适合信息/网络安全领域的学生以及刚入行业的从业者学习,原因如下:

    1. 覆盖面广。Security+认证学习的内容几乎涉及到了cyber security中的所有领域,官网的介绍如图所示。学习该认证能够帮助入门者快速建立对整个安全领域的宏观认识。
      在这里插入图片描述
    2. 学习内容难度不大。Security+作为一个入门认证,虽然覆盖了很多技术,但是很多的内容是点到为止,没有太过深入。当学习者完成了对于整个行业的初步学习后,可以进一步选择一个方向进行学习。
    3. 认证价格不贵。认证的费用大概是300多美元,换算后是2000多RMB。此外,不用报培训班,完全可以自己学习,节约培训成本。
    4. 提升英语水平。目前,对于Security+601的考试题目和学习课程(有字幕,语速适中清晰)都是全英文的,在学习过程中,能够帮助我们提升英语水平和熟悉更多的安全领域相关的名词。
    5. 没有工作年限要求。

    二、学习资料

    首先是学习视频。这里首推 Mike Chapple 在LinkedIn的学习资料(https://www.linkedin.com/learning/search?keywords=security%2B),课程大概20个小时左右,覆盖了所有的考试内容,有字幕,语速适中清晰。但是LinkedIn都课程中心已经不对中国大陆开放了,所以可以挂上VPN后注册一个海外账号, 然后免费领取1个月的学习会员进行学习(白嫖的好机会)。
    在这里插入图片描述
    第二,如果想要更加详细的学习知识点,并提升自己的英文材料阅读能力,可以去找一下security+ 601的学习指南的PDF(国内好像买不到纸质书)。该书的每一章节后面都有相关的测试题。
    在这里插入图片描述
    最后是我学习过程中翻译整理的 Mike Chapple 提供课程的学习笔记,链接如下:
    https://blog.csdn.net/tushanpeipei/article/details/120356937

    三、备考过程

    首先,Security+满分900分,750通过。考试的题目类型包括三种,由数目有多到少排序为:单选、多选和performance-based的题目(比如简单的配置防火墙,无线网络)。Performance-based大概会在整个考试中出现3道,然后总共的题目数量大约在80-90(MAX)道左右。

    目前,Security+601的考试题库大概有600道左右,可以选择去买一个口碑较好的Dumps题库。一般里面包含了考试的百分之90以上的题库内容。但是需要注意的是,其中大概只有百分之80-90的题目是正确的,所以我们需要对于其中自己不确定的题目进行确认,确认的主要两个网站分别是:Chegg(https://www.chegg.com/)和Examtopics(https://www.examtopics.com/)。当然,对于很多不确定的概念,可以直接翻阅Security+学生指南或者google搜索wiki等网站进行确认。

    其中Chegg主要是类似于百度知道的形式,如下所示:
    在这里插入图片描述
    当然这些”expert“回答的内容不一定是正确的,但是经过我的判断,大部分回答是没有问题的。

    对于Examtopics网站,里面目前有300道题左右,但是这个题库给出的很多答案也是错误的。好在它给了备考者一个交流讨论的平台,我们可以根据他们的讨论结果来最终判断自己该选择哪一个答案,具体页面如下所示:
    在这里插入图片描述
    当然,这两个网站如果都想查看完整的回答/题库,则需要付费,大概分别都是100RMB左右。

    最后就是买考卷然后进行考试了,考试提供了VUE的线上和线下两种形式,可以灵活选择,学习Mike Chapple课程或者买了学习指南,应该都可以拿到百分之10的折扣。

    此外,想最后补充一句,该版本的考试不太适合死记硬背通过,因为考试的时候大概率会碰到几道没有见过的题目,此外,题库中也有不少的题目是错误的,需要自己学习后进行判断。祝想要通过该考试的同学都能如尝所愿。

    展开全文
  • spring_security+OAuth2+JWT

    2021-05-05 15:13:29
    spring_security+OAuth2+JWT
  • Security+课程大纲
  • SpringBoot+SpringSecurity+WebSocket的整合Demo
  • 谷安天下Security+ ppt

    2019-02-25 18:13:25
    谷安天下Security+ ppt。 Security+ 谷安天下内部培训ppt 谷安天下 security加培训资料
  • CompTIA Security+ Guide to Network Security Fundamentals(5th) 英文无水印pdf 第5版 pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 ...
  • security+学习资料.zip

    2019-11-07 17:12:00
    Security+认证考试复习资料,主要内容包括:安全基础概念知识,网络安全知识,密码学知识,访问控制欲身份管理知识,安全威胁与漏洞介绍等等。
  • Security+ 认证

    2017-10-16 12:15:22
    Security+ 认证是一种中立第三方认证,其发证机构为美国计算机行业协会CompTIA
  • Springboot+Security+Jwt

    千次阅读 热门讨论 2021-12-13 16:45:12
    随着业务的发展,传统的不分离前后端的Java项目逐渐减少,更多的时候是做到前后端分离,会话管理也就从传统的Session会话管理变为Jwt管理会话,本篇文章就是SpringBoot使用Jwt管理会话同时整合Security,完成权限...


    工程目录

    文章目录



    前言

    随着业务的发展,传统的不分离前后端的Java项目逐渐减少,更多的时候是做到前后端分离,会话管理也就从传统的Session会话管理变为Jwt管理会话,本篇文章就是SpringBoot使用Jwt管理会话同时整合Security,完成权限操作。


    提示:以下是本篇文章正文内容,下面案例可供参考,可以按照工程目录进行拷贝搭建,希望对同行有所帮助!


    一、Security是什么?

    它是一个管理权限的框架,它包含了认证【即验证用户名密码】和授权【即用户可执行的操作】


    二、使用步骤


    1.引入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>
    
      <parent>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-parent</artifactId>
          <version>2.1.6.RELEASE</version>
      </parent>
    
      <groupId>Security_Jwt</groupId>
      <artifactId>Security_Jwt</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>war</packaging>
    
      <name>Security_Jwt Maven Webapp</name>
      <!-- FIXME change it to the project's website -->
      <url>http://www.example.com</url>
    
      <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>
          <junit.version>4.12</junit.version>
          <log4j.version>1.2.17</log4j.version>
          <lombok.version>1.14.8</lombok.version>
          <druid.version>1.1.16</druid.version>
          <commonslang.version>2.6</commonslang.version>
          <redis.version>2.1.3.RELEASE</redis.version>
          <springfox.version>2.7.0</springfox.version>
          <mybatis.plus.boot.starter.version>3.0.1</mybatis.plus.boot.starter.version>
          <pagehelper.spring.boot.starter.version>1.2.10</pagehelper.spring.boot.starter.version>
          <mysql-connector.version>5.1.39</mysql-connector.version>
      </properties>
    
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.security</groupId>
              <artifactId>spring-security-taglibs</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-security</artifactId>
          </dependency>
          <dependency>
              <groupId>org.thymeleaf.extras</groupId>
              <artifactId>thymeleaf-extras-springsecurity5</artifactId>
          </dependency>
    
          <!-- JWT依赖 -->
          <dependency>
              <groupId>org.springframework.security</groupId>
              <artifactId>spring-security-jwt</artifactId>
          </dependency>
          <dependency>
              <groupId>io.jsonwebtoken</groupId>
              <artifactId>jjwt</artifactId>
              <version>0.9.0</version>
          </dependency>
    
          <!-- 引入 lombok -->
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
              <version>${lombok.version}</version>
          </dependency>
    
          <!-- swagger -->
          <dependency>
              <groupId>io.springfox</groupId>
              <artifactId>springfox-swagger2</artifactId>
              <version>${springfox.version}</version>
          </dependency>
          <dependency>
              <groupId>io.springfox</groupId>
              <artifactId>springfox-swagger-ui</artifactId>
              <version>${springfox.version}</version>
          </dependency>
    
          <!-- pagehelper分页 -->
          <dependency>
              <groupId>com.github.pagehelper</groupId>
              <artifactId>pagehelper-spring-boot-starter</artifactId>
              <version>${pagehelper.spring.boot.starter.version}</version>
          </dependency>
    
          <!-- mybatis-plus -->
          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-boot-starter</artifactId>
              <version>${mybatis.plus.boot.starter.version}</version>
          </dependency>
    
          <!--mysql数据库依赖包-->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>${mysql-connector.version}</version>
          </dependency>
    
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-data-redis</artifactId>
              <version>${redis.version}</version>
          </dependency>
    
          <dependency>
              <groupId>com.alibaba</groupId>
              <artifactId>fastjson</artifactId>
              <version>1.2.70</version>
              <scope>compile</scope>
          </dependency>
          <dependency>
              <groupId>apache-lang</groupId>
              <artifactId>commons-lang</artifactId>
              <version>2.0</version>
          </dependency>
    
    
      </dependencies>
    
      <build>
        <finalName>Security_Jwt</finalName>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
          <plugins>
            <plugin>
              <artifactId>maven-clean-plugin</artifactId>
              <version>3.1.0</version>
            </plugin>
            <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
            <plugin>
              <artifactId>maven-resources-plugin</artifactId>
              <version>3.0.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-compiler-plugin</artifactId>
              <version>3.8.0</version>
            </plugin>
            <plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.22.1</version>
            </plugin>
            <plugin>
              <artifactId>maven-war-plugin</artifactId>
              <version>3.2.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-install-plugin</artifactId>
              <version>2.5.2</version>
            </plugin>
            <plugin>
              <artifactId>maven-deploy-plugin</artifactId>
              <version>2.8.2</version>
            </plugin>
          </plugins>
        </pluginManagement>
      </build>
    </project>


    2.application.yml文件

    代码如下:

    server:
      port: 8080
    
    #数据源
    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/my_security_test?useUnicode=true&characterEncoding=UTF-8
        username: root
        password: root
    #日期配置 yyyy-MM-dd HH:mm:ss
      jackson:
        date-format: yyyy-MM-dd HH:mm:ss
    
    #映射xml
    mybatis-plus:
      mapper-locations: classpath:mapping/*.xml
      type-aliases-package: com.dev.model
      configuration:
    #开启驼峰
        map-underscore-to-camel-case: true
    
    #分页插件
    pagehelper:
      auto-dialect: mysql
      reasonable: true
      support-methods-arguments: true
    
    # JWT配置
    jwt:
      # 密匙Key
      secret: limoumou
      # HeaderKey
      tokenHeader: Authorization
      # Token前缀
      tokenPrefix: Bearer
      # 过期时间,单位秒
      expiration: 86400
      # 配置白名单(不需要认证)
      antMatchers: /swagger-resources/**,/swagger-ui.html,/v2/api-docs,/webjars/**,/doc.html

    3.启动类App8080.java

    代码如下:

    package com.dev;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * @return {@link }
     * @throws
     * @author 李庆伟
     * @date 2021/7/14 14:41
     */
    @SpringBootApplication
    public class App8080 {
        public static void main(String[] args) {
            SpringApplication.run(App8080.class,args);
        }
    }

    4.Result.java

    代码如下:

    package com.dev.common;
    
    import com.alibaba.fastjson.JSON;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.Data;
    
    import javax.servlet.ServletResponse;
    import java.io.PrintWriter;
    import java.util.List;
    
    /**
     * @author 李庆伟
     * @date 2020/4/16 9:52
     */
    @Data
    public class Result {
    
        @ApiModelProperty(value = "返回码")
        private int code;
    
        @ApiModelProperty(value = "返回数据")
        private Object data;
    
        @ApiModelProperty(value = "返回描述")
        private String msg;
    
        @ApiModelProperty(value = "返回长度")
        private long count;
    
        /**返回成功 */
        public static Result success(List<Object> data, long count){
            Result result = new Result();
            result.setCode(0);//成功
            result.setMsg("成功");//提示语
            result.setData(data);
            result.setCount(count);
            return result;
        }
    
        /**返回成功 */
        public static Result success(List data){
            Result result = new Result();
            result.setCode(0);//成功
            result.setMsg("成功");//提示语
            result.setData(data);
            result.setCount(data == null || data.size() == 0 ? 0 : data.size());
            return result;
        }
    
        /**返回成功 */
        public static Result successForPage(List data,Integer count){
            Result result = new Result();
            result.setCode(0);//成功
            result.setMsg("成功");//提示语
            result.setData(data);
            result.setCount(count == null ? 0 : count);
            return result;
        }
    
        /**返回成功 */
        public static Result success(){
            Result result = new Result();
            result.setCode(0);//成功
            result.setMsg("成功");//提示语
            return result;
        }
    
        /**返回成功 */
        public static Result success(Object object){
            Result result = new Result();
            result.setCode(0);//成功
            result.setMsg("成功");//提示语
            result.setData(object);//返回内容
            return result;
        }
    
        /**返回失败 */
        public static Result error(){
            Result result = new Result();
            result.setCode(1);//失败
            result.setMsg("失败");//提示语
            return result;
        }
    
        /**返回失败 */
        public static Result error(int code, String msg){
            Result result = new Result();
            result.setCode(code);//失败
            result.setMsg(msg);//提示语
            return result;
        }
    
        /**返回信息*/
        public static Result response(int code, String msg, Object data) {
            Result result = new Result();
            result.setCode(code);
            result.setMsg(msg);
            result.setData(data);
            return result;
        }
    
        /**Response输出Json格式 */
        public static void responseJson(ServletResponse response, Object data) {
            PrintWriter out = null;
            try {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json");
                out = response.getWriter();
                out.println(JSON.toJSONString(data));
                out.flush();
            } catch (Exception e) {
                System.out.println("Response输出Json异常:" + e);
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        }
    
    }

    5.MyException.java

    代码如下:

    package com.dev.config.exception;
    
    /**
     * @author 李庆伟
     * @date 2020/4/16 10:10
     */
    public class MyException extends RuntimeException{
    
        private int code;
        private String msg;
    
        public MyException(int code, String msg){
            super(msg);
            this.code = code;
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
    }

    6.TopException

    代码如下:

    package com.dev.config.exception;
    
    import com.dev.common.Result;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @author 李庆伟
     * @date 2020/4/16 10:11
     */
    @ControllerAdvice
    public class TopException {
    
        private Logger logger = LoggerFactory.getLogger(this.getClass());
    
        @ExceptionHandler(value = Exception.class)
        @ResponseBody
        public Result handle(Exception e){
    
            if(e instanceof MyException){
                logger.error("业务日志",e);
                MyException myException = (MyException) e;
                return  Result.error(myException.getCode(),myException.getMessage());
            }else if(e instanceof AccessDeniedException){
                return  Result.error(403,"访问权限不足");
            }
    
            logger.error("系统日志",e);
            return Result.error(1000,"业务繁忙");
        }
    }

    7.UserAccessDeniedHandler

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.common.Result;
    import org.springframework.security.access.AccessDeniedException;
    import org.springframework.security.web.access.AccessDeniedHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * 无权限处理类
     * @author 李庆伟
     * @date 2021/7/26 10:00
     */
    @Component
    public class UserAccessDeniedHandler implements AccessDeniedHandler {
    
        @Override
        public void handle(HttpServletRequest request, HttpServletResponse response,
                           AccessDeniedException accessDeniedException) throws IOException, ServletException {
            Result.responseJson(response, Result.response(403, "权限不足,拒绝访问", accessDeniedException.getMessage()));
        }
    
    }

    8.UserAuthenticationProvider

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.config.security.Md5Util;
    import com.dev.model.SysUserDetails;
    import com.dev.service.impl.SysUserDetailsService;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.authentication.AuthenticationProvider;
    import org.springframework.security.authentication.BadCredentialsException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Component;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 10:49
     */
    @Component
    public class UserAuthenticationProvider implements AuthenticationProvider {
        @Autowired
        private SysUserDetailsService userDetailsService;
    
        /**
         * 身份验证
         */
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String username = (String) authentication.getPrincipal(); // 获取用户名
            String password = (String) authentication.getCredentials(); // 获取密码
            if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
                throw new UsernameNotFoundException("用户名或密码不能为空");
            }
            if(username.equals("admin") && password.equals("123456")){
                SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
                return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
            } else if (username.equals("admin") && !password.equals("123456")){
                throw new BadCredentialsException("用户名或密码错误");
            } else {
                SysUserDetails sysUserDetails = (SysUserDetails) userDetailsService.loadUserByUsername(username);
                if (sysUserDetails == null) {
                    throw new UsernameNotFoundException("用户名不存在");
                }
                if(!sysUserDetails.getPassword().equals(Md5Util.MD5(password))){
                    throw new BadCredentialsException("用户名或密码错误");
                }
                return new UsernamePasswordAuthenticationToken(sysUserDetails, password, sysUserDetails.getAuthorities());
            }
        }
    
        /**
         * 支持指定的身份验证
         */
        @Override
        public boolean supports(Class<?> authentication) {
            return true;
        }
    
    }

    9.UserLoginFailureHandler

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.common.Result;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.AuthenticationFailureHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 登录失败处理类
     * @author 李庆伟
     * @date 2021/7/26 10:03
     */
    @Component
    public class UserLoginFailureHandler implements AuthenticationFailureHandler {
    
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                            AuthenticationException exception) {
            Result.responseJson(response, Result.response(500, "登录失败", exception.getMessage()));
        }
    }

    10.UserLoginSuccessHandler

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.common.Result;
    import com.dev.config.security.JWTTokenUtil;
    import com.dev.model.SysUserDetails;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 登录成功处理类
     * @author 李庆伟
     * @date 2021/7/26 10:02
     */
    @Component
    public class UserLoginSuccessHandler implements AuthenticationSuccessHandler {
    
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                            Authentication authentication) {
            SysUserDetails sysUserDetails = (SysUserDetails) authentication.getPrincipal();
            String token = JWTTokenUtil.createAccessToken(sysUserDetails);
            Map<String, String> tokenMap = new HashMap<>();
            tokenMap.put("token", token);
            Result.responseJson(response, Result.response(0, "登录成功", tokenMap));
        }
    }

    11.UserLogoutSuccessHandler

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.common.Result;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 登出成功处理类
     * @author 李庆伟
     * @date 2021/7/26 10:04
     */
    @Component
    public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
    
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response,
                                    Authentication authentication) {
            SecurityContextHolder.clearContext();
            Result.responseJson(response, Result.response(200, "登出成功", null));
        }
    }

    12.UserNotLoginHandler

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.common.Result;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.AuthenticationEntryPoint;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author 李庆伟
     * @date 2021/7/27 15:39
     */
    @Component
    public class UserNotLoginHandler implements AuthenticationEntryPoint {
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
                             AuthenticationException authException) throws IOException, ServletException {
            Result.responseJson(response, Result.response(401, "未登录", authException.getMessage()));
        }
    }

    13.UserPermissionEvaluator

    代码如下:

    package com.dev.config.security.handler;
    
    import com.dev.config.exception.MyException;
    import com.dev.model.SysUserDetails;
    import com.dev.model.TSysRes;
    import com.dev.service.TSysResService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.access.PermissionEvaluator;
    import org.springframework.security.core.Authentication;
    import org.springframework.stereotype.Component;
    
    import java.io.Serializable;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 14:33
     */
    @Configuration
    @Component
    public class UserPermissionEvaluator implements PermissionEvaluator {
    
        @Autowired
        private TSysResService tSysResService;
    
        /**
         * 判断是否拥有权限
         * [authentication, targetUrl, permission]
         * @return {@link boolean}
         * @throws
         * @author 李庆伟
         * @date 2021/12/7 19:42
         */
        @Override
        public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
            SysUserDetails sysUserDetails = null;
            try {
                sysUserDetails = (SysUserDetails) authentication.getPrincipal();
            } catch (Exception e){
                throw new MyException(403,"权限不足");
            }
    
            Set<String> permissions = new HashSet<String>(); // 用户权限
    
            List<TSysRes> authList = tSysResService.findResByUserId(sysUserDetails.getId());
    
            for (int i = 0; i < authList.size() ; i++) {
                permissions.add(authList.get(i).getPermission());
            }
    
            // 判断是否拥有权限
            if (permissions.contains(permission.toString())) {
                return true;
            }
            return false;
        }
    
        @Override
        public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
                                     Object permission) {
            return false;
        }
    
    }

    14.AutoSecurityConfig

    代码如下:

    package com.dev.config.security;
    
    import com.dev.config.security.handler.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    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.http.SessionCreationPolicy;
    import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 14:36
     */
    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法权限注解
    public class AutoSecurityConfig extends WebSecurityConfigurerAdapter {
    
        /**
         * 无权限处理类
         */
        @Autowired
        private UserAccessDeniedHandler userAccessDeniedHandler;
    
        /**
         * 用户未登录处理类
         */
        @Autowired
        private UserNotLoginHandler userNotLoginHandler;
    
        /**
         * 用户登录成功处理类
         */
        @Autowired
        private UserLoginSuccessHandler userLoginSuccessHandler;
    
        /**
         * 用户登录失败处理类
         */
        @Autowired
        private UserLoginFailureHandler userLoginFailureHandler;
    
        /**
         * 用户登出成功处理类
         */
        @Autowired
        private UserLogoutSuccessHandler userLogoutSuccessHandler;
    
        /**
         * 用户登录验证
         */
        @Autowired
        private UserAuthenticationProvider userAuthenticationProvider;
    
        /**
         * 用户权限注解
         */
        @Autowired
        private UserPermissionEvaluator userPermissionEvaluator;
    
        /**
         * 加密方式,没使用这种加密方式
         */
        @Bean
        public BCryptPasswordEncoder bCryptPasswordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        /**
         * 注入自定义PermissionEvaluator
         *
         * @return
         */
        @Bean
        public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler() {
            DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
            handler.setPermissionEvaluator(userPermissionEvaluator);
            return handler;
        }
    
        /**
         * 用户登录验证
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) {
            auth.authenticationProvider(userAuthenticationProvider);
        }
    
    
        @Value("${jwt.antMatchers}")
        private String antMatchers;//白名单,这里是不做验证的方法
        /**
         * 安全权限配置
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() // 权限配置
                    .antMatchers(antMatchers.split(",")).permitAll()// 获取白名单(不进行权限验证)
                    .anyRequest().authenticated() // 其他的需要登陆后才能访问
                    .and().httpBasic().authenticationEntryPoint(userNotLoginHandler) // 配置未登录处理类
                    .and().formLogin().loginProcessingUrl("/user/login")// 配置登录URL
                    //.and().formLogin().loginPage("/user/login")// 配置登录URL
                    .successHandler(userLoginSuccessHandler) // 配置登录成功处理类
                    .failureHandler(userLoginFailureHandler) // 配置登录失败处理类
                    .and().logout().logoutUrl("/logout/submit")// 配置登出地址
                    .logoutSuccessHandler(userLogoutSuccessHandler) // 配置用户登出处理类
                    .and().logout()   //退出登录相关配置
                          .logoutSuccessUrl("/page/index") //退出成功后跳转的页面
                          .deleteCookies("JSESSIONID")    //退出时要删除的Cookies的名字
                    .and().exceptionHandling().accessDeniedHandler(userAccessDeniedHandler)// 配置没有权限处理类
                    .and().cors()// 开启跨域
                    .and().csrf().disable(); // 禁用跨站请求伪造防护
            http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 禁用session(使用Token认证)
            http.headers().cacheControl(); // 禁用缓存
            http.addFilter(new JWTAuthenticationFilter(authenticationManager()));  添加JWT过滤器
        }
    
    }
    

    15.JWTAuthenticationFilter

    代码如下:

    package com.dev.config.security;
    
    import com.dev.model.SysUserDetails;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.context.SecurityContextHolder;
    import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
    
    import javax.servlet.FilterChain;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 10:52
     */
    public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
    
        public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
            super(authenticationManager);
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws IOException, ServletException {
            // 取出Token
            String token = request.getHeader(JWTConfig.tokenHeader);
    
            if (token != null && token.startsWith(JWTConfig.tokenPrefix)) {
                SysUserDetails sysUserDetails = JWTTokenUtil.parseAccessToken(token);
    
                if (sysUserDetails != null) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            sysUserDetails, sysUserDetails.getId(), sysUserDetails.getAuthorities());
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
            filterChain.doFilter(request, response);
        }
    
    }

    16.JWTConfig

    代码如下:

    package com.dev.config.security;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 9:54
     */
    @Component
    @ConfigurationProperties(prefix = "jwt")
    public class JWTConfig {
    
        /**
         * 密匙Key
         */
        public static String secret;
    
        /**
         * HeaderKey
         */
        public static String tokenHeader;
    
        /**
         * Token前缀
         */
        public static String tokenPrefix;
    
        /**
         * 过期时间
         */
        public static Integer expiration;
    
        /**
         * 配置白名单
         */
        public static String antMatchers;
    
        /**
         * 将过期时间单位换算成毫秒
         *
         * @param expiration 过期时间,单位秒
         */
        public void setExpiration(Integer expiration) {
            this.expiration = expiration * 1000;
        }
    
        public void setSecret(String secret) {
            this.secret = secret;
        }
    
        public void setTokenHeader(String tokenHeader) {
            this.tokenHeader = tokenHeader;
        }
    
        public void setTokenPrefix(String tokenPrefix) {
            this.tokenPrefix = tokenPrefix + " ";
        }
    
        public void setAntMatchers(String antMatchers) {
            this.antMatchers = antMatchers;
        }
    
    }

    17.JWTTokenUtil

    代码如下:

    package com.dev.config.security;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.TypeReference;
    import com.dev.model.SysUserDetails;
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    
    import java.util.*;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 9:57
     */
    @Slf4j
    public class JWTTokenUtil {
    
        /**
         * 创建Token
         *
         * @param sysUserDetails 用户信息
         * @return
         */
        public static String createAccessToken(SysUserDetails sysUserDetails) {
            String token = Jwts.builder().setId(// 设置JWT
                    sysUserDetails.getId()) // 用户Id
                    .setSubject(sysUserDetails.getUsername()) // 主题
                    .setIssuedAt(new Date()) // 签发时间
                    .setIssuer("limoumou") // 签发者
                    .setExpiration(new Date(System.currentTimeMillis() + JWTConfig.expiration)) // 过期时间
                    .signWith(SignatureAlgorithm.HS512, JWTConfig.secret) // 签名算法、密钥
                    .claim("authorities", JSON.toJSONString(sysUserDetails.getAuthorities())).compact(); // 自定义其他属性,如用户组织机构ID,用户所拥有的角色,用户权限信息等
            return JWTConfig.tokenPrefix + token;
        }
    
        /**
         * 解析Token
         *
         * @param token Token信息
         * @return
         */
        public static SysUserDetails parseAccessToken(String token) {
            SysUserDetails sysUserDetails = null;
            if (StringUtils.isNotEmpty(token)) {
                try {
                    // 去除JWT前缀
                    token = token.substring(JWTConfig.tokenPrefix.length());
    
                    // 解析Token
                    Claims claims = Jwts.parser().setSigningKey(JWTConfig.secret).parseClaimsJws(token).getBody();
    
                    // 获取用户信息
                    sysUserDetails = new SysUserDetails();
                    sysUserDetails.setId(claims.getId());
                    sysUserDetails.setUsername(claims.getSubject());
                    // 获取角色
                    Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
                    String authority = claims.get("authorities").toString();
                    if (StringUtils.isNotEmpty(authority)) {
                        List<Map<String, String>> authorityList = JSON.parseObject(authority,
                                new TypeReference<List<Map<String, String>>>() {
                                });
                        for (Map<String, String> role : authorityList) {
                            if (!role.isEmpty()) {
                                authorities.add(new SimpleGrantedAuthority(role.get("authority")));
                            }
                        }
                    }
                    sysUserDetails.setAuthorities(authorities);
                } catch (Exception e) {
                    log.error("解析Token异常:" + e);
                }
            }
            return sysUserDetails;
        }
    
    }

    18.Md5Util

    代码如下:

    package com.dev.config.security;
    
    import java.security.MessageDigest;
    
    /**
     * @author 李庆伟
     * @date 2021/7/28 15:54
     */
    public class Md5Util {
    
        public final static String MD5(String s) {
            char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
            try {
                // 密码+盐组合
                byte[] btInput = s.getBytes();
                // 获得MD5摘要算法的 MessageDigest 对象
                MessageDigest mdInst = MessageDigest.getInstance("MD5");
                // 使用指定的字节更新摘要
                mdInst.update(btInput);
                // 获得密文
                byte[] md = mdInst.digest();
                // 把密文转换成十六进制的字符串形式
                int j = md.length;
                char str[] = new char[j * 2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    str[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(str);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         * 测试
         * [args]
         * @throws
         * @author 李庆伟
         * @date 2021/12/13 19:38
         */
        public static void main(String[] args) {
            String pwd = Md5Util.MD5("123456");
            System.out.println(pwd );
        }
    }

    19.SwaggerConfig

    代码如下:

    package com.dev.config;
    
    import com.dev.App8080;
    import com.fasterxml.classmate.TypeResolver;
    import com.google.common.collect.Sets;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.HttpMethod;
    import org.springframework.http.MediaType;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.OperationBuilder;
    import springfox.documentation.builders.ParameterBuilder;
    import springfox.documentation.builders.RequestHandlerSelectors;
    import springfox.documentation.schema.ModelRef;
    import springfox.documentation.service.ApiDescription;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.service.Parameter;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.ApiListingScannerPlugin;
    import springfox.documentation.spi.service.contexts.DocumentationContext;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.spring.web.readers.operation.CachingOperationNameGenerator;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * 接口文档配置
     * @return {@link }
     * @throws
     * @author 李庆伟
     * @date 2021/7/19 17:15
     */
    @ConditionalOnWebApplication
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig implements ApiListingScannerPlugin {
    
        /**
         * Swagger2的配置文件,这里可以配置Swagger2的一些基本的内容,比如扫描的包等等
         * []
         * @return {@link Docket}
         * @throws
         * @author 李庆伟
         * @date 2021/12/13 16:28
         */
        @Bean
        public Docket createRestApi() {
    
            List<Parameter> pars = new ArrayList<>();
            ParameterBuilder token = new ParameterBuilder();
            token.name("Authorization").description("Authorization")
                    .modelRef(new ModelRef("string"))
                    .parameterType("header")
                    .required(false).build();
            pars.add(token.build());
    
            ParameterBuilder languageCode = new ParameterBuilder();
            languageCode.name("languageCode").description("languageCode")
                    .modelRef(new ModelRef("string"))
                    .parameterType("header")
                    .required(false).build();
            pars.add(languageCode.build());
    
            return new Docket(DocumentationType.SWAGGER_2)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage(App8080.class.getPackage().getName()))
                    .build()
                    .globalOperationParameters(pars)
                    .apiInfo(apiInfo());
    
        }
    
        /**
         * 构建API文档的详细信息函数
         * @return
         */
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("项目接口 API")
                    .version("1.0")
                    .build();
        }
    
    
        /**
         * Security指定的登录接口不会出现在swagger中,为了方便可以自定义登录接口在swagger中。
         * [documentationContext]
         * @return {@link List<ApiDescription>}
         * @throws
         * @author 李庆伟
         * @date 2021/12/13 16:20
         */
        @Override
        public List<ApiDescription> apply(DocumentationContext documentationContext) {
            return new ArrayList<ApiDescription>(
                    Arrays.asList(
                            new ApiDescription(
                                    "/user/login",  //url
                                    "登录", //描述
                                    Arrays.asList(
                                            new OperationBuilder(
                                                    new CachingOperationNameGenerator())
                                                    .method(HttpMethod.POST)//http请求类型
                                                    .produces(Sets.newHashSet(MediaType.APPLICATION_JSON_VALUE))
                                                    .summary("登录")
                                                    .notes("登录")//方法描述
                                                    .tags(Sets.newHashSet("登录"))//归类标签
                                                    .parameters(
                                                            Arrays.asList(
                                                                    new ParameterBuilder()
                                                                            .description("用户名")
                                                                            .type(new TypeResolver().resolve(String.class))
                                                                            .name("username")
                                                                            .parameterType("query")
                                                                            .parameterAccess("access")
                                                                            .required(true)
                                                                            .modelRef(new ModelRef("string")) //<5>
                                                                            .build(),
                                                                    new ParameterBuilder()
                                                                            .description("密码")
                                                                            .type(new TypeResolver().resolve(String.class))
                                                                            .name("password")
                                                                            .parameterType("query")
                                                                            .parameterAccess("access")
                                                                            .required(true)
                                                                            .modelRef(new ModelRef("string")) //<5>
                                                                            .build()
                                                            ))
                                                    .build()),
                                    false)));
        }
    
        @Override
        public boolean supports(DocumentationType documentationType) {
            return DocumentationType.SWAGGER_2.equals(documentationType);
        }
    }

    20.TSysUserController

    代码如下:

    package com.dev.controller;
    
    import com.dev.common.Result;
    import io.swagger.annotations.*;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.web.bind.annotation.*;
    
    
    /**
     * 系统用户服务
     * @author 李庆伟
     * @date 2021/7/19 17:04
     */
    @Slf4j
    @RequestMapping("tSysUser")
    @RestController
    @Api(value = "系统用户服务", tags = "系统用户服务")
    public class TSysUserController {
    
        @PreAuthorize("hasRole('ROLE_/tSysUser/findByPage')")
        @PostMapping("findByPage")
        @ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
        public Result findByPage(){
            log.info("测试用户分页查询权限");
            return Result.success("测试用户分页查询权限");
        }
    
        @PreAuthorize("hasRole('ROLE_/tSysUser/add')")
        @PostMapping("add")
        @ApiOperation(value = "添加系统用户", notes = "添加系统用户", produces = "application/json")
        public Result add(){
            log.info("测试用户添加权限");
            return Result.success("测试用户添加权限");
        }
    
        @PreAuthorize("hasRole('ROLE_/tSysUser/edit')")
        @PostMapping("edit")
        @ApiOperation(value = "修改系统用户", notes = "修改系统用户", produces = "application/json")
        public Result edit(){
            log.info("测试用户编辑权限");
            return Result.success("测试用户编辑权限");
        }
    
        @PreAuthorize("hasRole('ROLE_/tSysUser/delete')")
        @PostMapping("delete")
        @ApiOperation(value = "删除系统用户", notes = "删除系统用户", produces = "application/json")
        public Result delete(){
            log.info("测试用户删除权限");
            return Result.success("测试用户删除权限");
        }
    }

    21.TSysResMapper

    代码如下:

    package com.dev.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.dev.model.TSysRes;
    import org.apache.ibatis.annotations.Mapper;
    
    
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Mapper
    public interface TSysResMapper extends BaseMapper<TSysRes> {
    
    
    }

    22.TSysRoleMapper

    代码如下:

    package com.dev.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.dev.model.TSysRole;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    
    import java.util.List;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Mapper
    public interface TSysRoleMapper extends BaseMapper<TSysRole> {
    
        /**
         * 根据用户名查询用户有的角色
         * [userId]
         * @return {@link List<TSysRole>}
         * @throws
         * @author 李庆伟
         * @date 2021/7/27 14:40
         */
        @Select("SELECT r.* FROM t_sys_role r " +
                "LEFT JOIN t_sys_user_role ur ON ur.role_id = r.id " +
                "WHERE " +
                "ur.user_id = #{userId} ")
        List<TSysRole> findRoleByUserId(String userId);
    
    
    }

    23.TSysRoleResMapper

    代码如下:

    package com.dev.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.dev.model.TSysRoleRes;
    import org.apache.ibatis.annotations.Mapper;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Mapper
    public interface TSysRoleResMapper extends BaseMapper<TSysRoleRes> {
    
        List<String> selectRoleResByMap(Map<String, Object> map);
        
    }

    24.TSysUserMapper

    代码如下:

    package com.dev.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.dev.model.TSysUser;
    import org.apache.ibatis.annotations.Mapper;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Mapper
    public interface TSysUserMapper extends BaseMapper<TSysUser> {
    
    
    }

    25.TSysUserRoleMapper

    代码如下:

    package com.dev.dao;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.dev.model.TSysUserRole;
    import org.apache.ibatis.annotations.Mapper;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Mapper
    public interface TSysUserRoleMapper extends BaseMapper<TSysUserRole> {
    
    
    }
    

    26.SysUserDetails

    代码如下:

    package com.dev.model;
    
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.io.Serializable;
    import java.util.Collection;
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 9:48
     */
    @Data
    @EqualsAndHashCode(callSuper = false)
    public class SysUserDetails extends TSysUser implements UserDetails, Serializable {
        private static final long serialVersionUID = 1L;
    
        /**
         * 用户角色
         */
        private Collection <GrantedAuthority> authorities;
    
        /**
         * 账号是否过期
         */
        private boolean isAccountNonExpired = false;
    
        /**
         * 账号是否锁定
         */
        private boolean isAccountNonLocked = false;
    
        /**
         * 证书是否过期
         */
        private boolean isCredentialsNonExpired = false;
    
        /**
         * 账号是否有效
         */
        private boolean isEnabled = true;
    
        /**
         * 获得用户权限
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return authorities;
        }
    
        /**
         * 判断账号是否过期
         */
        @Override
        public boolean isAccountNonExpired() {
            return isAccountNonExpired;
        }
    
        /**
         * 判断账号是否锁定
         */
        @Override
        public boolean isAccountNonLocked() {
            return isAccountNonLocked;
        }
    
        /**
         * 判断证书是否过期
         */
        @Override
        public boolean isCredentialsNonExpired() {
            return isCredentialsNonExpired;
        }
    
        /**
         * 判断账号是否有效
         */
        @Override
        public boolean isEnabled() {
            return isEnabled;
        }
    
    }

    27.TSysRes

    代码如下:

    package com.dev.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.util.Date;
    
    /**
     * 系统资源实体
     * @return {@link }
     * @throws
     * @author 李庆伟
     * @date 2021/7/22 9:25
     */
    @Data
    @TableName("t_sys_res")
    public class TSysRes {
    
        @TableId
        private String id;//主键
        private String name;//资源名称
        private String resUrl;//资源路径
        private String permission;//做拦截的code
        private String resType;//0菜单   1按钮
        private String pid;//父级id
        private String icon;//菜单图标
        private String createUser;//创建人
        private Date createDate;//创建时间
    
    }

    28.TSysRole

    代码如下:

    package com.dev.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.util.Date;
    
    /**
     * 系统角色实体
     * @author 李庆伟
     * @date 2021/7/19 17:00
     */
    @Data
    @TableName("t_sys_role")
    public class TSysRole {
    
        @TableId
        private String id;//主键
        private String roleName;//角色名称
        private String roleExplain;//角色描述
        private String createUser;//创建人
        private Date createDate;//创建时间
    
    }

    29.TSysRoleRes

    代码如下:

    package com.dev.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    
    /**
     * 系统角色资源实体
     * @author 李庆伟
     * @date 2021/7/19 17:00
     */
    @Data
    @TableName("t_sys_role_res")
    public class TSysRoleRes {
    
        @TableId
        private String id;//主键
        private String roleId;//角色id
        private String resId;//资源id
    
    }

    30.TSysUser

    代码如下:

    package com.dev.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * 系统用户实体
     * @author 李庆伟
     * @date 2021/7/19 17:00
     */
    @Data
    @TableName("t_sys_user")
    public class TSysUser implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @TableId
        private String id;//主键
        private String username;//用户名
        private String password;//密码
        private String nickName;//昵称
        private String cellPhone;//电话
        private String mail;//邮件
        private Date birthday;//生日
        private String status;//状态(0-正常,1-禁用,2-删除)
        private String accountType;//1系统账号 2客户账号
        private String inviteCode;//邀请码
        private String sex;//性别:0男 1女
        private String address;//地址
        private Integer upNum;//获赞总量
        private Integer readNum;//文章被阅读总量
        private String sign;//签名
        private String pictureId;//用户头像
        private String createUser;//创建人
        private Date createDate;//创建时间
    
    }

    31.TSysUserRole

    代码如下:

    package com.dev.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    /**
     * 系统用户角色实体
     * @author 李庆伟
     * @date 2021/7/19 17:00
     */
    @Data
    @TableName("t_sys_user_role")
    public class TSysUserRole {
    
        @TableId
        private String id;//主键
        private String userId;//用户名id
        private String roleId;//角色id
    }

    32.SysUserDetailsService

    代码如下:

    package com.dev.service.impl;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.dev.model.SysUserDetails;
    import com.dev.model.TSysRes;
    import com.dev.model.TSysUser;
    import com.dev.dao.TSysResMapper;
    import com.dev.service.TSysResService;
    import com.dev.service.TSysUserService;
    import com.github.pagehelper.util.StringUtil;
    import org.springframework.beans.BeanUtils;
    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.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    
    /**
     * @author 李庆伟
     * @date 2021/7/26 10:44
     */
    @Service
    public class SysUserDetailsService  implements UserDetailsService {
    
        @Autowired
        private TSysUserService tSysUserService;
    
        @Resource
        private TSysResMapper tSysResMapper;
    
        @Autowired
        private TSysResService tSysResService;
    
        /**
         * 说明:重写UserDetailsService中的loadUserByUsername,就是查询用户详细信息封装到 UserDetails
         * 业务:
         *      ①如果是admin会拥有全部权限
         *      ②如果不是admin就去查用户信息和用户拥有的权限
         * [username]
         * @return {@link UserDetails}
         * @throws
         * @author 李庆伟
         * @date 2021/12/7 19:49
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            List<TSysRes> resList = null;
            if(username.equals("admin")){
                TSysUser tSysUser = new TSysUser();
                tSysUser.setId("admin");
                tSysUser.setUsername("admin");
                tSysUser.setNickName("系统管理员");
                SysUserDetails sysUserDetails = new SysUserDetails();
                BeanUtils.copyProperties(tSysUser, sysUserDetails);
                Set<GrantedAuthority> authorities = new HashSet<>(); // 角色集合
    
                //admin用户有的资源集合
                resList = tSysResMapper.selectList(new QueryWrapper<>());
                for (int i = 0; i < resList.size() ; i++) {
                    if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
                        authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
                    }
                }
                sysUserDetails.setAuthorities(authorities);
                return sysUserDetails;
            }
            TSysUser tSysUser = tSysUserService.findByUsername(username);
            if (tSysUser != null) {
                SysUserDetails sysUserDetails = new SysUserDetails();
                BeanUtils.copyProperties(tSysUser, sysUserDetails);
    
                Set<GrantedAuthority> authorities = new HashSet<>(); // 角色集合
    
                resList = tSysResService.findResByUserId(sysUserDetails.getId());//当前用户有的资源集合
                if(resList != null){
                    for (int i = 0; i < resList.size() ; i++) {
                        if(StringUtil.isNotEmpty(resList.get(i).getPermission())){
                            authorities.add(new SimpleGrantedAuthority("ROLE_" + resList.get(i).getPermission()));
                        }
                    }
                }
                sysUserDetails.setAuthorities(authorities);
                return sysUserDetails;
            }
            return null;
        }
    }

    33.TSysResServiceImpl

    代码如下:

    package com.dev.service.impl;
    
    import com.dev.model.TSysRes;
    import com.dev.model.TSysRole;
    import com.dev.dao.TSysResMapper;
    import com.dev.dao.TSysRoleMapper;
    import com.dev.dao.TSysRoleResMapper;
    import com.dev.service.TSysResService;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    
    /**
     * 系统角色服务
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Service
    public class TSysResServiceImpl implements TSysResService {
    
        @Resource
        private TSysResMapper tSysResMapper;
    
        @Resource
        private TSysRoleMapper tSysRoleMapper;
    
        @Resource
        private TSysRoleResMapper tSysRoleResMapper;
        /**
         * 根据用户id查询用户拥有的资源
         * [userId]
         * @return {@link List< TSysRes>}
         * @throws
         * @author 李庆伟
         * @date 2021/12/7 20:34
         */
        @Override
        public List<TSysRes> findResByUserId(String userId) {
            //获取用户有的角色
            //根据当前登录用户获取角色
            List<TSysRole> roleList = tSysRoleMapper.findRoleByUserId(userId);
            if(roleList == null || roleList.size() == 0){ //如果用户没有角色返回没有权限
                return null;
            }
            //根据角色获取菜单资源id关系集合
            Map<String,Object> map = new HashMap<>();
            map.put("roleList",roleList);
            List<String> tSysRoleResList = tSysRoleResMapper.selectRoleResByMap(map);
            if(tSysRoleResList == null || tSysRoleResList.size() == 0){ //如果用户没有角色返回没有权限
                return null;
            }
            //根据资源id获取菜单资源
            return tSysResMapper.selectBatchIds(tSysRoleResList);
    
        }
    
    }

    34.TSysRoleResServiceImpl

    代码如下:

    package com.dev.service.impl;
    
    import com.dev.service.TSysRoleResService;
    import org.springframework.stereotype.Service;
    
    
    
    /**
     * 系统角色资源服务
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Service
    public class TSysRoleResServiceImpl implements TSysRoleResService {
    
    }

    35.TSysRoleServiceImpl

    代码如下:

    package com.dev.service.impl;
    
    import com.dev.service.TSysRoleService;
    import org.springframework.stereotype.Service;
    
    
    
    /**
     * 系统角色服务
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Service
    public class TSysRoleServiceImpl implements TSysRoleService {
    
    
    }

    36.TSysUserRoleServiceImpl

    代码如下:

    package com.dev.service.impl;
    
    import com.dev.service.TSysUserRoleService;
    import org.springframework.stereotype.Service;
    
    
    
    /**
     * 系统用户角色服务
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Service
    public class TSysUserRoleServiceImpl implements TSysUserRoleService {
    
    
    }

    37.TSysUserServiceImpl

    代码如下:

    package com.dev.service.impl;
    
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.dev.model.TSysUser;
    import com.dev.dao.TSysUserMapper;
    import com.dev.service.TSysUserService;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    
    /**
     * 系统用户服务
     * @author 李庆伟
     * @date 2021/7/19 17:06
     */
    @Service
    public class TSysUserServiceImpl implements TSysUserService {
    
    
        @Resource
        private TSysUserMapper tSysUserMapper;
    
    
        /**
         * 根据用户名查询用户
         * [username]
         * @return {@link TSysUser}
         * @throws
         * @author 李庆伟
         * @date 2021/7/27 11:11
         */
        public TSysUser findByUsername(String username) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("username",username);
            return tSysUserMapper.selectOne(queryWrapper);
        }
    
    
    }

    38.TSysResService

    代码如下:

    package com.dev.service;
    
    import com.dev.model.TSysRes;
    
    import java.util.List;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:05
     */
    public interface TSysResService {
    
        List<TSysRes> findResByUserId(String userId);
    
    }

    39.TSysRoleResService

    代码如下:

    package com.dev.service;
    
    
    
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:05
     */
    public interface TSysRoleResService {
    
    
    }

    40.TSysRoleService

    代码如下:

    package com.dev.service;
    
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:05
     */
    public interface TSysRoleService {
    
    
    }

    41.TSysUserRoleService

    代码如下:

    package com.dev.service;
    
    
    
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:05
     */
    public interface TSysUserRoleService {
    
    }

    42.TSysUserServiceImpl

    代码如下:

    package com.dev.service;
    
    
    import com.dev.model.TSysUser;
    
    /**
     * @author 李庆伟
     * @date 2021/7/19 17:05
     */
    public interface TSysUserService {
    
        TSysUser findByUsername(String username);
    
    }



    库表【跟上篇文章的一样】:

     

     导入数据库sql

    /*
     Navicat Premium Data Transfer
    
     Source Server         : 本机数据库mysql
     Source Server Type    : MySQL
     Source Server Version : 50143
     Source Host           : localhost:3306
     Source Schema         : my_security_test
    
     Target Server Type    : MySQL
     Target Server Version : 50143
     File Encoding         : 65001
    
     Date: 08/12/2021 21:17:27
    */
    
    SET NAMES utf8mb4;
    SET FOREIGN_KEY_CHECKS = 0;
    
    -- ----------------------------
    -- Table structure for t_sys_res
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_res`;
    CREATE TABLE `t_sys_res`  (
      `id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id',
      `name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源名称',
      `res_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源路径',
      `permission` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '资源code',
      `res_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '0菜单   1按钮',
      `pid` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父级id',
      `create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
      `create_date` datetime DEFAULT NULL,
      `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '菜单图标'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-资源表【菜单】' ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- Records of t_sys_res
    -- ----------------------------
    INSERT INTO `t_sys_res` VALUES ('101', '用户添加', '/tSysUser/add', '/tSysUser/add', '1', '100', NULL, NULL, '');
    INSERT INTO `t_sys_res` VALUES ('100', '用户管理', '/tSysUser/findByPage', '/tSysUser/findByPage', '0', '', NULL, NULL, 'fa fa-snowflake-o');
    INSERT INTO `t_sys_res` VALUES ('102', '用户修改', '/tSysUser/edit', '/tSysUser/edit', '1', '100', NULL, NULL, 'fa fa-home');
    INSERT INTO `t_sys_res` VALUES ('103', '用户删除', '/tSysUser/delete', '/tSysUser/delete', '1', '100', NULL, NULL, 'fa fa-home');
    
    -- ----------------------------
    -- Table structure for t_sys_role
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_role`;
    CREATE TABLE `t_sys_role`  (
      `id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
      `role_name` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色名称',
      `role_explain` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '描述',
      `create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
      `create_date` datetime DEFAULT NULL COMMENT '创建时间'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色表' ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- Records of t_sys_role
    -- ----------------------------
    INSERT INTO `t_sys_role` VALUES ('277144172094291968', '部门经理', '部门经理', NULL, '2021-08-27 10:22:51');
    INSERT INTO `t_sys_role` VALUES ('277144675716956160', '普通员工', '普通员工', NULL, '2021-08-27 10:24:51');
    INSERT INTO `t_sys_role` VALUES ('277646459757658112', '测试员工', '测试员工', '', '2021-08-28 19:38:46');
    
    -- ----------------------------
    -- Table structure for t_sys_role_res
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_role_res`;
    CREATE TABLE `t_sys_role_res`  (
      `id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
      `role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
      `res_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '资源id'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-角色资源表中间表' ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- Records of t_sys_role_res
    -- ----------------------------
    INSERT INTO `t_sys_role_res` VALUES ('1234', '277144675716956160', '101');
    INSERT INTO `t_sys_role_res` VALUES ('12345', '277144675716956160', '100');
    INSERT INTO `t_sys_role_res` VALUES ('123456', '277144172094291968', '100');
    INSERT INTO `t_sys_role_res` VALUES ('123457', '277144172094291968', '101');
    INSERT INTO `t_sys_role_res` VALUES ('123458', '277144172094291968', '102');
    
    -- ----------------------------
    -- Table structure for t_sys_user
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_user`;
    CREATE TABLE `t_sys_user`  (
      `id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
      `username` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户名',
      `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '密码',
      `nick_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '昵称',
      `cell_phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机号',
      `mail` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮件',
      `birthday` datetime DEFAULT NULL COMMENT '生日',
      `status` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '状态(0-正常,1-删除,2-禁用)',
      `account_type` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '1系统账号 2客户账号',
      `invite_code` varchar(60) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邀请码',
      `sex` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '性别:0男 1女',
      `up_num` int(11) DEFAULT NULL COMMENT '所有获赞总量',
      `read_num` int(11) DEFAULT NULL COMMENT '所有文章阅读总量',
      `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '地址',
      `create_user` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '创建人',
      `create_date` datetime DEFAULT NULL COMMENT '创建时间',
      `sign` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户签名',
      `picture_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '用户头像'
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户表' ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- Records of t_sys_user
    -- ----------------------------
    INSERT INTO `t_sys_user` VALUES ('276866508766838784', 'liqingwei', 'E10ADC3949BA59ABBE56E057F20F883E', '李庆伟', '15801174628', 'liqingwei01@cnpc.cn', NULL, '0', '1', '3781941dd39446b89e98cb661766aade', NULL, 0, 0, NULL, NULL, '2021-08-26 15:59:31', NULL, NULL);
    INSERT INTO `t_sys_user` VALUES ('277657251341139964', 'zhangsan', 'E10ADC3949BA59ABBE56E057F20F883E', '张三', '15801174626', 'zhangsan@qq.com', '2021-08-04 00:00:00', '0', '1', 'ea819ca462914e938943752d48ae8bcc', '0', 0, 0, '河南北京北', 'admin', '2021-08-28 20:21:38', '啥也不是。。。', '287348042074423296');
    
    -- ----------------------------
    -- Table structure for t_sys_user_role
    -- ----------------------------
    DROP TABLE IF EXISTS `t_sys_user_role`;
    CREATE TABLE `t_sys_user_role`  (
      `id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',
      `user_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用户id',
      `role_id` varchar(38) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
      PRIMARY KEY (`id`) USING BTREE
    ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '系统-用户角色中间表' ROW_FORMAT = Compact;
    
    -- ----------------------------
    -- Records of t_sys_user_role
    -- ----------------------------
    INSERT INTO `t_sys_user_role` VALUES ('111', '276866508766838784', '277144675716956160');
    INSERT INTO `t_sys_user_role` VALUES ('222', '277657251341139964', '277144172094291968');
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    测试【把登录接口加到swagger中了】:

    访问地址:http://localhost:8080/swagger-ui.html

    总结

    一点点。。。。。。。。。。。

    展开全文
  • Spring Security + Oauth2 认证授权

    千次阅读 2022-05-02 18:45:42
    文章目录前言一、Spring Security + Oauth2 认证的4种模式1.1 授权码模式1.2 简化模式1.3 密码模式1.4 客户端模式二、使用步骤1.引入库2.读入数据总结 前言 微服务开发这么流行,安全认证非常重要,Spring Security...

    相对较全面的 Spring Security Oauth2 认证授权框架


    前言

    微服务开发这么流行,安全认证非常重要,Spring Security + Oauth2 作为一个 认证授权的框架,不可缺。
    在此简单说明并且做学习笔记。
    开发工具:IDEA


    一、Spring Security + Oauth2 认证的4种模式

    1.1 授权码模式(authorization_code)

    授权码是相对比较安全的模式,需要用户首先通过接口获取一个 授权码,然后再用 client_id 和 client_secret 加上 获取到的授权码进行认证。

    1.2 简化模式(implicit)

    简化模式多用于单一应用,没有服务端的第三方单页面应用,因为没有服务器端就无法接受授权码。

    1.3 密码模式 (password)

    密码模式一般用于我们自己开发的,第一方原生APP或者是第一方面页面应用;因为会暴露密码出来,所以最好client端是自己开发的或者我们比较信任的

    1.4 客户端模式(client_credentials)

    我们对client足够信任的情况下使用客户端模式,客户端本身提供的 client_id 和 client_secret 进行认证

    二、项目搭建

    2.1 添加依赖 pom.xml

    因为使用的是 Spring security + Oauth2 进行认证与授权的,所以要添加 Spring security 和 Oauth2 的依赖包;
    也是一个web项目,所以需要添加 boot 的 web 包。
    版本:版本是 2.x

    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-oauth2</artifactId>
            </dependency>
        </dependencies>
    

    2.2 配置安全规则

    2.2.1 web安全规则配置

    2.2.2.1 规则配置类

    @Configuration
    @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Resource
        ClientAccessDeniedHandler clientAccessDeniedHandler;
    
        @Autowired
        UsernamePasswordAuthenticationProvider usernamePasswordAuthenticationProvider;
    
        /**
         * 配置 Http 请求 安全策略
         * @param http
         * @throws Exception
         */
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()  //关闭 csrf 保护
              	.authorizeRequests().antMatchers(HttpMethod.OPTIONS,"/login","/oauth/**").permitAll() //配置哪些路径可以访问
                    .anyRequest().authenticated() //配置所有的请求都要权限验证
                    .and()
                    .formLogin().loginPage("/login.html") //自定义登录页面
                    .and()
                    .exceptionHandling().accessDeniedHandler(clientAccessDeniedHandler); //配置访问受限时的情况
            //super.configure(http);
        }
    
        /**
         * 配置一个 provider 进行用户信息的获取和验证操作
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.authenticationProvider(usernamePasswordAuthenticationProvider);
        }
    
        /**
         * 初始化一个 provider 提供校验操作
         * @return
         * @throws Exception
         */
        @Bean
        public AuthenticationManager authenticationManager() throws Exception {
            return new ProviderManager(usernamePasswordAuthenticationProvider);
        }
    
        /**
         * 设置密码加密方式
         * @return
         */
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    }
    

    2.2.2.2 依赖的认证操作 provider

    @Component
    public class UsernamePasswordAuthenticationProvider implements AuthenticationProvider {
    
        /**
         * 这里使用 UserDetailService 进行加载用户信息
         */
        @Autowired
        WeshUserDetailService userDetailService;
    
        /**
         * 认证方法
         * @param authentication
         * @return
         * @throws AuthenticationException
         */
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            String principle = authentication.getPrincipal().toString(); //username
            String credential = authentication.getCredentials().toString(); //password
            UserDetails userDetails = userDetailService.loadUserByUsername(principle);
            return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),userDetails.getAuthorities());
        }
    
        /**
         * 判断是不是使用此 provider 进行认证操作,返回true 则在认证的时候执行上面的 authenticate() 方法
         * @param aClass
         * @return
         */
        @Override
        public boolean supports(Class<?> aClass) {
            return aClass.equals(UsernamePasswordAuthenticationToken.class);
        }
    }
    
    

    2.2.2.3 加载用户信息的 UserDetailsService

    @Component
    public class WeshUserDetailService implements UserDetailsService {
    
        /**
         * 框架会掉此方法加载用户信息
         * @param username
         * @return
         * @throws UsernameNotFoundException
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            if("100001".equals(username)){
                User user = new User("100001","admin001", Collections.emptyList());
                return user;
            }
            return null;
        }
    }
    

    2.2.2 认证规则配置

    2.2.2.1 规则配置

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter{
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private JwtAccessTokenConverter jwtAccessTokenConverter;
    
        @Autowired
        private WeshClientDetailsService clientDetailsService;
    
        @Autowired
        private TokenStore tokenStore;
    
        /**
         * 配置登录用户信息服务
         * @param configurer
         * @throws Exception
         */
        @Override
        public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
            //配置数据库获取客户信息
            configurer.withClientDetails(clientDetailsService);
            //super.configure(clients);
        }
    
        /**
         * 配置令牌
         * @param endpoints
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager) //需要提供一个认证管理器
                    .accessTokenConverter(jwtAccessTokenConverter) //jwt 进行密码转换加密
                    .tokenServices(tokenServices()) //token 管理服务
                    .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    
            //super.configure(endpoints);
        }
    
        /**
         * 配置终端(api)
         * @param security
         * @throws Exception
         */
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.tokenKeyAccess("permitAll()") //token/token_key
                    .checkTokenAccess("permitAll()") //check_token
                    .allowFormAuthenticationForClients(); //允许表单认证提交,不放开,登录页面表单提交不了
            //super.configure(security);
        }
    
        @Bean
        public AuthorizationServerTokenServices tokenServices(){
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setClientDetailsService(clientDetailsService); //配置生成token获取用户信息服务
            tokenServices.setTokenStore(tokenStore); //token 存储服务
            tokenServices.setReuseRefreshToken(true);
            tokenServices.setAccessTokenValiditySeconds(7200);
            tokenServices.setReuseRefreshToken(false); // 设置为 true, 则没有 refresh_token 在返回体中
            tokenServices.setSupportRefreshToken(true); //支持 refresh token
            tokenServices.setRefreshTokenValiditySeconds(259200); //刷新令牌3天有效期
            //设置token的加密方式为 JWT
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));
            tokenServices.setTokenEnhancer(tokenEnhancerChain);
            return tokenServices;
        }
    }
    

    2.2.2.2 客户端信息查询服务

    @Service
    public class WeshClientDetailsService implements ClientDetailsService {
    
        /**
         * 实现具体如何读取用户信息
         * 项目中可以用从数据库中查询
         * @param s
         * @return
         * @throws ClientRegistrationException
         */
        @Override
        public ClientDetails loadClientByClientId(String s) throws ClientRegistrationException {
            Client client = new Client();
            if("100001".equals(clientId)){  //授权码模式需要提供跳转地址 100001 作为授权码账号
                client.setClientId("100001");
                client.setClientSecret(new BCryptPasswordEncoder().encode("admin001"));
                client.getScope().add("all"); //权限范围是all,所有
                client.getAuthorizedGrantTypes().add("authorization_code");
                client.getRegisteredRedirectUri().add("http://www.baidu.com");
            }
            if("100002".equals(clientId)){ // 100002 作为 password 模式跳转
                client.setClientId("100002");
                client.setClientSecret(new BCryptPasswordEncoder().encode("admin001"));
                client.getScope().add("all"); //权限范围是all,所有
            }
            return client;
        }
    }
    

    2. Token 配置

    /**
     * Token 配置 jwt 加密
     */
    @Configuration
    public class TokenConfig {
    
        /**
         * jwt 配置的一个 签名
         */
        private final String SIGNING_KEY = "*****";
    
        /**
         * 初始化 token store 来存储token
         * @return
         */
        @Bean
        public TokenStore tokenStore(){
            return new JwtTokenStore(jwtAccessTokenConverter());
        }
    
        /**
         * jwt 加密token配置
         * @return
         */
        @Bean
        public JwtAccessTokenConverter jwtAccessTokenConverter(){
            JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();
            tokenConverter.setSigningKey(SIGNING_KEY);
            return tokenConverter;
        }
    }
    

    2.3 启动测试

    2.3.1 授权码测试

    2.3.1.1 请求获取授权码

    http://localhost:9999/uaa/oauth/authorize?client_id=client01&response_type=code&scope=all&redirect_uri=http://www.baidu.com (GET)

    参数说明:
    client_id: 用户id
    client_secret: 用户密码
    response_type: 请求认证方式,值为 ‘code’
    输入用户名密码后,跳转到授权页面
    点击Authorize之后,会跳转到 redirect url,并传参授权码
    code 就是授权码

    2.3.1.2 请求认证接口

    按照授权码获取token
    授权码授权成功

    2.3.2 简化模式测试

    2.3.2.1 请求

    http://localhost:9999/uaa/oauth/authorize?client_id=client01&response_type=token&scope=all&redirect_uri=http://www.baidu.com (GET)
    注意:response_type是 token
    调用授权接口,和 授权码模式同一个接口,不过 response_type 是 token
    注意:response_type是token

    2.3.2.2 响应跳转

    返回结果:
    注意:链接中的 ‘#’ , URI 中的 fragment 用来标识初级资源
    跳转回来接口带了 token

    2.3.3 密码模式测试

    http://localhost:9999/uaa/oauth/token(POST)
    参数
    client_id=client01,
    client_secret=client01,
    grant_type=password,
    username=zhangsan,
    password=123
    密码模式直接获取token

    2.3.4 客户端模式测试

    http://localhost:9999/uaa/oauth/token
    参数
    client_id=client01
    client_secret=client01
    grant_type=client_credentials
    客户端模式直接获取token

    总结

    spring security + oauth2进行了简单的搭建和记录,大致理解了 spring security oauth2 框架,项目初始搭建完成,不过此框架还有很多细节部分需要再深究。
    自己总结的往往影响比较深刻,哪怕忘记了,看自己的文章也更熟悉。
    而且我的文章目录清晰,可以迅速定位到需要看的那部分。
    项目源码
    有详细注释。
    如果令尊看到这里了,希望不要浪费您的宝贵的实际,这篇简短的文章能帮助到令尊!!!

    展开全文
  • security+ 备考专用笔记

    2019-04-22 09:13:58
    security+ 备考专用笔记 知识点概念等备考总结,security+ 备考专用笔记 知识点概念等备考总结。
  • SpringBoot+SpringSecurity+JWT实现认证和授权

    万次阅读 多人点赞 2021-01-17 23:40:52
    dbcp,c3p0) SpringBoot+SpringSecurity+mysql实现认证与授 SpringBoot+Spring Security基于内存用户认证 SpringBoot+WebSocket在线聊天室、消息推送 SpringBoot+SpringData JPA操作Mysql数据库 SpringBoot热部署...
  • Spring Security + OAuth2.0

    千次阅读 2021-02-17 16:26:45
    授权服务器 授权服务器中有4个端点。说明如下: Authorize Endpoint :授权端点,进行...Spring Security Oauth2架构 说明如下: 用户访问,此时没有Token。Oauth2RestTemplate会报错,这个报错信息会被Oauth2Cli
  • 前后端分离 -- Spring Boot + Spring Security + Vue + ElementUI 实现用户认证

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,137,217
精华内容 454,886
关键字:

Security+