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

文章目录

  • 认证流程
  • 创建工程
    • 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 {//视图解析器@Beanpublic InternalResourceViewResolver viewResolver() {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setPrefix("/WEB-INF/view/");viewResolver.setSuffix(".jsp");return viewResolver;}@Autowiredprivate SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");}
}

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


public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {//spring容器@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[]{ApplicationConfig.class};}//servletContext@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[]{WebConfig.class};}//url-mapping@Overrideprotected 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中配置,将根目录指向登录页

//指向登录页面@Overridepublic 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 {@Overridepublic 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 {@AutowiredAuthenticationService 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 {@Overridepublic 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注册拦截器

    @Autowiredprivate SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");}

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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HuggingGPT解析:使用 ChatGPT及HuggingFace上的族系解决AI问题

HuggingGPT解析&#xff1a;使用 ChatGPT及HuggingFace上的族系解决AI问题 HuggingGPT是一个利用大型语言模型(LLMs)来解决复杂AI任务的框架。其基本理念是&#xff0c;考虑到LLMs&#xff08;例如ChatGPT&#xff09;在语言理解、生成、交互和推理方面展现出了卓越的能力&…

Spring Boot 中的 @Scheduled 注解是什么,如何使用

Spring Boot 中的 Scheduled 注解是什么&#xff0c;如何使用 引言 Spring Boot 是一个非常流行的 Java Web 开发框架&#xff0c;它提供了很多方便的功能&#xff0c;其中就包括了 Scheduled 注解。本文将会介绍 Scheduled 注解的基本用法&#xff0c;并附上代码示例&#x…

使用wxPtyon和pillow开发拼图小游戏(一)

刚学习python&#xff0c;心血来潮&#xff0c;使用wxPython和pillow开了一个简单的拼图小游戏&#xff0c;大家分享一下 wxPython是Python语言的一套优秀的GUI图形库&#xff0c;在此项目里主要用来开发GUI客户页面&#xff1b;Pillow是一个非常好用的图像处理库&#xff0c;…

【学习】ChatGPT对问答社区产生了哪些影响?

引用 StackExchange 社区 CEO Prashanth Chandrasekar 的一篇博客标题 “Community is the future of AI”&#xff0c;引出本文的观点&#xff0c;即ChatGPT对问答社区产生了颠覆性影响&#xff0c;问答社区必须釜底抽薪、涅槃重生&#xff0c;但我们必须坚信“社区才是AI的未…

pycharm 配置github

文章目录 环境必备操作步骤1.在pycharm中配置git和github2.获取ssh密钥3.将本地项目与github仓库连接4.同步本地项目到github 相关问题参考文章 环境必备 pycharm 2020.1&#xff1a;集成开发环境&#xff0c;需要安装并配置环境 PyCharm 开发环境搭建指南&#xff1a;安装、配…

Jmeter之数据参数化方法汇总

一、什么是参数化 Jmeter参数化是指将脚本中的某些需要输入数据使用参数来代替&#xff0c;在脚本运行时指定参数的取值范围和规则。脚本在运行时就可以根据需要选取不同的参数值作为输入。 常用的Jmeter的参数化请求&#xff0c;包括以下几种方式&#xff1a; 用户参数用户…

LRU 缓存

题目链接 LRU 缓存 题目描述 注意点 如果插入操作导致关键字数量超过 capacity &#xff0c;则应该 逐出 最久未使用的关键字函数 get 和 put 必须以 O(1) 的平均时间复杂度运行 解答思路 如果想以O(1)的速度进行get&#xff0c;则需要将对应的key、value存到map中如果想…

gitlab:(二)gitlab添加win10 台式机的ssh key

当前gitlab版本为12系列&#xff1a; 点击settings 找到ssh keys &#xff0c;再找到“ generate one or use an existing key.” 点击 generate one 参考如下的教程&#xff1a; window cmd 命令行示例 添加 ssh keys 添加的效果

Qt DAY5 Qt制作简易网络聊天室

服务器 widget.h文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QTcpSocket> #include <QVector>//向量&#xff0c;函数类模板 #include <QMessageBox>namespace Ui { class Widget; }class Wid…

python接口自动化(二十五)--unittest断言——下(详解)

简介 本篇还是回归到我们最初始的话题&#xff0c;想必大家都忘记了&#xff0c;没关系看这里&#xff1a;传送门 没错最初的话题就是登录&#xff0c;由于博客园的登录机制改变了&#xff0c;本篇以我找到的开源免费的登录API为案例&#xff0c;结合 unittest 框架写 2 个用例…

使用json-server 模拟后端数据

1. json-server是什么 json-server 是一个 Node 模块&#xff0c;运行 Express 服务器&#xff0c;你可以指定一个 json 文件作为 api 的数据源。 简单的说&#xff0c;它可以模拟小型后台接口&#xff0c;在一个JSON文件中操作数据&#xff0c;是基于的node.js的一个模块。 比…

Python批量实现word中查找关键字

一、背景 在日常办公和文档处理中&#xff0c;我们常常需要在大量的Word文档中查找特定的关键字&#xff0c;然后进行接下来的操作&#xff0c;比如关键字替换等。手动逐个打开并搜索文档显然是费时费力的。因此&#xff0c;利用Python编写一个批量实现Word中查找关键字的程序可…