Spring Security OAuth2.0(2):基于session的认证方式

news2024/11/26 12:41:28

文章目录

  • 认证流程
  • 创建工程
    • 1 创建maven工程
    • 2. 实现认证功能
    • 3. 会话功能
    • 4. 授权功能

认证流程

\qquad 基于session的认证方式如下
\qquad 它的交互流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的session_id存放到cookie中,这样用户客户端请求时带上session_id就可以验证服务器端是否存在session数据,以此完成用户的合法验证,当用户退出系统或session过期销毁时,客户端的session_id也就无效了。
在这里插入图片描述
基于Session的认证机制由Servlet规范定制,Servlet容器已实现,用户通过HttpSession的操作方式即可实现,如下是HttpSession相关的操作API。

方法解释
HttpSession getSession(Boolean create)获取当前HttpSession对象
void setAttribute(String name,Object value)向当前session中存储对象
Object getAttribute(String name)从session中取对象
void removeAttribue(String name)移除session中的对象
void invalidate()使HttpSession失效

创建工程

案例使用maven构建,使用SpringMVC,Servlet3.0实现。

本章代码已分享至Gitee: https://gitee.com/lengcz/security-springmvc

1 创建maven工程

结构预览
在这里插入图片描述

(1)选择maven(不选择maven模板),创建maven工程
在这里插入图片描述
(2)配置pom文件
在这里插入图片描述

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

    <groupId>com.it2</groupId>
    <artifactId>security-springmvc</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.12</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>security-springmvc</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.tomcat.maven</groupId>
                    <artifactId>tomcat7-maven-plugin</artifactId>
                    <version>2.2</version>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <configuration>
                        <encoding>utf-8</encoding>
                        <useDefaultDelimiters>true</useDefaultDelimiters>
                        <resources>
                            <resource>
                                <directory>src/main/resources</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>**/*</include>
                                </includes>
                            </resource>
                            <resource>
                                <directory>src/main/java</directory>
                                <filtering>true</filtering>
                                <includes>
                                    <include>**/*.xml</include>
                                </includes>
                            </resource>
                        </resources>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>


</project>

(3) Spring容器配置
在config包下定义ApplicationConfig.java,它对应web.xml中ContextLoaderListener的配置

/**
 * config包下定义ApplicationConfig.java,它对应web.xml中ContextLoaderListener的配置
 */
@Configuration  //相当于ApplicationContext.xml
@ComponentScan(basePackages = "com.it2.security.springmvc",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class ApplicationConfig {
    //在此配置除了Controller的其它bean,比如:数据库连接池,事务管理器,业务bean等

}

(4) servletContext配置
本案例采用Servlet3.0无web.xml方式,在config包下定WebConfig.java,它对应DispatcherServlet配置

@Configuration //相当于springmvc.xml
@EnableWebMvc
@ComponentScan(basePackages = "com.it2.security.springmvc",
        includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
public class WebConfig implements WebMvcConfigurer {

    //视图解析器
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/view/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    

    @Autowired
    private SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");
    }
}

(5)加载Spring容器
在init包下定义Spring容器初始化类SpringApplicationInitializer,此类实现WebApplicationInitializer接口,Spring容器加载启动时加载WebApplicationInitializer接口的所有实现类。


public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    //spring容器
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{ApplicationConfig.class};
    }

    //servletContext
    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebConfig.class};
    }

    //url-mapping
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

2. 实现认证功能

(1) 在view目录下编写一个登录页面,login.jsp
在这里插入图片描述

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

</html>

(2) 在WebConfig.java中配置,将根目录指向登录页

//指向登录页面
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("login");
    }

(3) 编写登录认证接口
用户进入认证页面后,输入账号和密码,点击登录,请求/login进行身份认证。

  • 定义认证接口,此接口用来校验传递过来的用户名、密码校验,若成功则返回该用户的详细信息,否则抛出错误异常:
public interface AuthenticationService {

    /**
     * 用户认证
     *
     * @param authenticationRequest
     * @return
     */
    UserDto authentication(AuthenticationRequest authenticationRequest);
}

认证请求实体和返回实体

/**
 * 认证请求参数
 */
@Data
public class AuthenticationRequest {

    private String username;

    private String password;

}
/**
 * 用户信息
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
public class UserDto {

    public static final String SESSION_USER_KEY = "_user";

    private String id;

    private String username;

    private String password;

    private String fullname;

    private String mobile;

    /**
     * 用户权限
     */
    private Set<String> authorities;

}

(3) 编写校验实现类

package com.it2.security.springmvc.service;

import com.it2.security.springmvc.model.AuthenticationRequest;
import com.it2.security.springmvc.model.UserDto;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Service
public class AuthenticationServiceImpl implements AuthenticationService {
    @Override
    public UserDto authentication(AuthenticationRequest authenticationRequest) {
        if (null == authenticationRequest || StringUtils.isEmpty(authenticationRequest.getUsername()) ||
                StringUtils.isEmpty(authenticationRequest.getPassword())) {
            throw new RuntimeException("账号或密码不能为空");
        }
        UserDto userDto = getUserDto(authenticationRequest.getUsername());
        if (null == userDto) {
            throw new RuntimeException("用户不存在");
        }

        if (!authenticationRequest.getPassword().equals(userDto.getPassword())) {
            throw new RuntimeException("密码错误");
        }
        return userDto;
    }

    public UserDto getUserDto(String username) {
        return userMap.get(username);
    }

    private Map<String, UserDto> userMap = new HashMap<>();

    {
        Set<String> authorities1 = new HashSet<>();
        authorities1.add("p1");
        Set<String> authorities2 = new HashSet<>();
        authorities2.add("p2");
        userMap.put("xiaowang", new UserDto("10", "xiaowang", "123456", "小王", "13800000000", authorities1));
        userMap.put("xiaoyu", new UserDto("11", "xiaoyu", "111111", "小鱼", "13900000000", authorities2));
    }
}

(4) 定义登录接口

@RestController
public class LoginController {

    @Autowired
    AuthenticationService authenticationService;

    @RequestMapping(value = "/login", produces = "text/plain;charset=utf-8")
    public String login(AuthenticationRequest authenticationRequest, HttpSession session) {
        UserDto userDto = authenticationService.authentication(authenticationRequest);
        session.setAttribute(UserDto.SESSION_USER_KEY, userDto);
        return userDto.getUsername() + "登录成功";
    }
    @RequestMapping(value = "/logout", produces = "text/plain;charset=utf-8")
    public String logout(AuthenticationRequest authenticationRequest, HttpSession session) {
        session.invalidate();
        return "登出成功";
    }
}    
    

(5)配置启动

#启动命令
clean tomcat7:run

在这里插入图片描述
(6) 启动服务测试
在这里插入图片描述

在这里插入图片描述

3. 会话功能

在上面,在登录成功会将用户存入session,在访问资源时getSession获取用户身份信息,在登出时,使session 无效已完成会话。
在这里插入图片描述

4. 授权功能

(1)首先给用户添加权限
在这里插入图片描述
在这里插入图片描述

(2)定义拦截器,用于处理权限

//权限拦截
@Component
public class SimpleAuthenticationInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //取出用户信息,判断请求的url是否在用户的权限范围内
        String requestURI = request.getRequestURI();
        Object object = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);
        if (null == object) {
            writeContent(response, "请登录");
            return false;
        }
        UserDto userDto = (UserDto) object;
        Set<String> authorities = userDto.getAuthorities();
        if (authorities.contains("p1") && requestURI.contains("/r/r1")) {
            return true;
        }
        if (authorities.contains("p2") && requestURI.contains("/r/r2")) {
            return true;
        }
        writeContent(response, "没有权限");
        return false;
    }

    private void writeContent(HttpServletResponse response, String msg) throws IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        writer.print(msg);
        writer.close();
    }
}

(3)在WebConfig.java注册拦截器

    @Autowired
    private SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");
    }

(4)启动服务测试,登录xiaowang账号,访问资源测试,分别方位r2和r1,可以看到xiaowang在访问r2时没有权限,而可以访问r1
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/722512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

银河麒麟服务器v10 sp1 部署.Net6.0 http https

上一篇&#xff1a;银河麒麟服务器V10 SP1 .Net6.0 开机自动启动_csdn_aspnet的博客-CSDN博客 参考微软官网&#xff1a;ASP.NET Core 中的 Kestrel Web 服务器 | Microsoft Learn 为 ASP.NET Core Kestrel Web 服务器配置终结点 | Microsoft Learn 注意&#xff1a;使用此…

【云效】使用流水线进行应用部署

目录 前言一、部署应用步骤1、创建流水线2、编辑流水线源3、编辑java构建上传4、编辑主机部署 前言 「流水线」&#xff0c;又名「Flow」&#xff0c;是阿里云「云效」产品矩阵中的一款企业级自动化研发交付工具。 它提供了灵活易用的持续集成、持续验证和持续发布功能&#…

基于springboot+mybatis-plus+mysql+vue实现物流信息管理系统(课设)

基于springbootmybatis-plusmysqlvue实现物流信息管理系统&#xff08;课设&#xff09; 一、系统介绍1、系统主要功能&#xff1a;2、环境配置 二、功能展示1.登陆2.用户管理3.个人信息4.物流管理 三、其它系统四、获取源码 一、系统介绍 1、系统主要功能&#xff1a; 用户&…

ElasticSearch 快速上手教程 (二) —— 基本概念术语

上一部分&#xff0c;我们讲解了 ES 的一些基本概念和应用场景&#xff0c;以及如何在本机搭建一个 ELK 测试环境。现在这篇文章带你了解 ES 当中一些基本术语以及相关的工作原理。 基本的概念术语 node(节点) ES 的一个运行实例&#xff0c;存储了部分文档数据&#xff0c;属…

文件包含基础

实验目的 通过本实验&#xff0c;理解文件包含的基本方法及文件包含需要注意的问题&#xff0c;为熟练掌握文件包含方法及防御奠定基础。 实验环境 操作机&#xff1a;kali 靶机&#xff1a;Windows 实验地址&#xff1a;http://靶机ip/exp/include/include1.php 用户名&…

ABC 195 C

不知道该怎么解释这道题&#xff0c;反正我不太会&#xff0c;感觉很帅 题意&#xff1a; Code&#xff1a; #include <bits/stdc.h>#define int long longusing namespace std;const int mxn2e310; const int mxe2e510; const int mod1e97; const int Inf1e18;int N;v…

基于FreeRTOS的嵌入式设备管理关键技术研究及实现(学习四)

硬件平台 终端设备的硬件选型主要由STM32芯片作为处理器&#xff0c;板载时钟电路和电源电路以及对外通信串口&#xff0c;并挂载AM2302温湿度传感器来实时收集环境相关信息&#xff0c;将收集到的信息通过NB-IoT通信模组上传到云端&#xff0c;从而实现整个环境监测功能。 主…

【重拾计划】模板 | N进制加法

N进制加法模板 基本原理 n进制转十进制&#xff0c;利用字符串处理&#xff0c;由于位数不同&#xff0c;采用倒序处理字符串。 代码实现 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> usin…

phpoffice/phpspreadsheet读取excel表格中的图片并保存到本地

我们开发导入excel表格功能时&#xff0c;会遇到表格中带有图片的情况&#xff0c;怎样获取到表格的图片并且把图片保存到本地&#xff0c;这样就可以展示你导入的数据和图片&#xff0c;实现此功能。 这里介绍一下分别使用phpspreadsheet和PHPExcel扩展库来实现读取Excel内图片…

win10multiple editions意思详细介绍

multiple editions是win10系统的一个版本号&#xff0c;很多的小伙伴都不知道这个英文是什么意思&#xff0c;今天就给你们带来了win10multiple editions意思详细介绍&#xff0c;还不清楚的就快来看看吧。 multiple editions是什么意思&#xff1a; 1、multiple editions是多…

C++笔记之内置基本类型的默认构造函数

C笔记之内置基本类型的默认构造函数 code review! 文章目录 C笔记之内置基本类型的默认构造函数1.C中基本内置类型的默认构造函数2.C有没有一个“内置构造函数”这样一个名词&#xff1f;3.基本内置类型按照前面提到的规则进行初始化是C11才开始的新特性吗&#xff1f; 1.C中…

【NX】NXOpen::BlockStyler::Tree的个人使用类分享

网上关于NXOpen::BlockStyler::Tree的例子不是太多&#xff0c;控件默认id名称为tree_control01&#xff0c;因为例子不多很多功能得自己写&#xff0c;虽然NXOpen::BlockStyler::Tree的封装已经不错了&#xff0c;但是实际使用起来也不是很方便&#xff0c;比如像获取所有节点…

基于PyQt5的桌面图像调试仿真平台开发(8)锐化

系列文章目录 基于PyQt5的桌面图像调试仿真平台开发(1)环境搭建 基于PyQt5的桌面图像调试仿真平台开发(2)UI设计和控件绑定 基于PyQt5的桌面图像调试仿真平台开发(3)黑电平处理 基于PyQt5的桌面图像调试仿真平台开发(4)白平衡处理 基于PyQt5的桌面图像调试仿真平台开发(5)…

机器学习基础之《特征工程(2)—特征工程介绍》

一、什么是特征工程 机器学习领域的大神Andrew Ng(吴恩达)老师说“Coming up with features is difficult, time-consuming, requires expert knowledge. “Applied machine learning” is basically feature engineering. ” 注&#xff1a;业界广泛流传&#xff1a;数据和特…

论文阅读-DF-Platter: Multi-Face Heterogeneous Deepfake Dataset(多人脸异构深度伪造数据集)

一、论文信息 文章名称&#xff1a;DF-Platter: Multi-Face Heterogeneous Deepfake Dataset 作者团队&#xff1a; 会议&#xff1a;cvpr2023 数据集地址&#xff1a;http://iab-rubric.org/df-platter-database 二、动机与创新 动机 目前大多数研究工作都集中在个人外表…

【零基础入门学习Python---Python中安全编程和测试之快速入门实践】

&#x1f680; 零基础入门学习Python&#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜…

Mysql基础之SQL语句

作定期复习和查询用&#xff0c;打开这篇博客提高效率&#xff0c;避免回视频或者百度上找 &#x1f442; 无论你多怪异我还是会喜欢你&#xff08;《刺客伍六七》动画推广版片尾曲&#xff09; - 周子琰 - 单曲 - 网易云音乐 内容来自B站黑马Mysql&#xff0c;检索使用 附上…

浅析Lambda架构

大家好&#xff0c;今天我们来介绍一个用于亿级实时数据分析架构Lambda架构。 Lambda架构 Lambda架构&#xff08;Lambda Architecture&#xff09;是由Twitter工程师南森马茨&#xff08;Nathan Marz&#xff09;提出的大数据处理架构。这一架构的提出基于马茨在BackType和Tw…

Python GUI编程利器:Tkinker中的消息和文本(7)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日目标 实现下面效果&#xff1a; 消息(Message类) 消息用于显示多行文本消息&#xff0c;对标签进行替代&#xff0c;如果…

【数学建模】国赛真题分析 2012 A题 葡萄酒的评价

2012 A题 葡萄酒的评价 优秀论文地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/19WGpybgM6RncxTYhx61JRA?pwdvl22 提取码&#xff1a;vl22 –来自百度网盘超级会员V6的分享 确定葡萄酒质量时一般是通过聘请一批有资质的评酒员进行品评。每个评酒员在对葡萄酒进…