今天手撸一个简易版本的springsecurity,带大家理解下springsecurity的原理。转载自:www.javaman.cn 手撸一个springsecurity,了解一下security原理

安全框架的两个特点就是认证和授权,让我们来通过代码了解下认证和授权的处理方式:

1、认证
认证就是指需要登录才能进行系统操作,如:登录qq、微信或者是web系统的登录都是认证的过程

1.1 工程目录

1.2 maven配置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 https://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.6.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.dashi</groupId><artifactId>security</artifactId><version>0.0.1-SNAPSHOT</version><name>security</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

1.3 application.yml配置如下

spring:mvc:view:prefix: /suffix: .html

1.4 创建User,模拟springsecurity的用户信息的核心接口UserDetails

import lombok.AllArgsConstructor;
import lombok.Data;@Data
@AllArgsConstructor
public class User {private Integer id;private String username;private String password;
}

1.5 创建AuthenticationService,模拟springsecurity的UserDetailsService核心接口

public interface AuthenticationService {public User authentication(AuthenticationRequest authenticationRequest);
}

1.6 实现AuthenticationService,模拟实现UserDetailsService的过程

@Service
public class AuthenticationServiceImpl implements AuthenticationService {private Map<String,User> users =  new HashMap<String,User>();@Overridepublic User authentication(AuthenticationRequest authenticationRequest) {if(authenticationRequest == null||"".equals(authenticationRequest.getUsername())||"".equals(authenticationRequest.getPassword())){throw new RuntimeException("用户名或密码为空");}User user = users.get(authenticationRequest.getUsername());if(user == null){throw new RuntimeException("用户不存在");}if(!user.getPassword().equals(authenticationRequest.getPassword())){throw new RuntimeException("密码不正确");}return user;  //模拟实现UserDetailS的User}public User getUser(String username){return users.get(username);}//创建两个账户,模拟管理员和普通的来宾用户{users.put("admin",new User(1,"admin","123"));  //管理员users.put("guest",new User(2,"guest","111"));  //来宾账户}
}

1.7 接收请求参数封装对象

@Data
public class AuthenticationRequest {private String username;private String password;
}

1.8 登录Controller,对/login请求处理,它调用AuthenticationService完成认证并返回登录结果提示信息

@Controller
public class LoginController {@Autowiredprivate AuthenticationService authenticationService;@GetMapping("/login")public String login(){return "login";}@PostMapping(value = "/login",produces = {"text/plain;charset=UTF-8"})public String login(AuthenticationRequest authenticationRequest, Model model){System.out.println("111"+authenticationRequest);User user = authenticationService.authentication(authenticationRequest);String loginMsg = user.getUsername()+"登录成功";System.out.println(loginMsg);model.addAttribute("loginMsg",loginMsg);return "loginsuccess";}
}

1.9 认证页面

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<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="登录1">
</form>
</body>
</html>

1.10 认证成功后打印登录成功页面

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><title>Title</title>
</head>
<body><h1 th:text="${loginMsg}"></h1>
</body>
</html>

1.11 测试具体页面
1)登录界面如下:

2)密码错误界面

3)登录成功界面

2、授权
授权就是控制什么样的用户或者角色访问什么功能,例如:管理员可以访问全部功能,guest普通用户只能访问某一个菜单或者功能

2.1 User增加权限authorities和session

package com.dashi.security.model;import lombok.AllArgsConstructor;
import lombok.Data;import java.util.Set;@Data
@AllArgsConstructor
public class User {private Integer id;private String username;private String password;//登录用户,增加登录用户sessionpublic static final String LOGIN_USER = "user";/*** 用户权限*/private Set<String> authorities;
}

2.2 用户增加角色authorities

import com.dashi.security.model.AuthenticationRequest;
import com.dashi.security.model.User;
import com.dashi.security.service.AuthenticationService;
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 {private Map<String,User> users =  new HashMap<String,User>();@Overridepublic User authentication(AuthenticationRequest authenticationRequest) {if(authenticationRequest == null||"".equals(authenticationRequest.getUsername())||"".equals(authenticationRequest.getPassword())){throw new RuntimeException("用户名或密码为空");}User user = users.get(authenticationRequest.getUsername());if(user == null){throw new RuntimeException("用户不存在");}if(!user.getPassword().equals(authenticationRequest.getPassword())){throw new RuntimeException("密码不正确");}return user;}public User getUser(String username){return users.get(username);}{//增加管理员权限Set<String> authorities1 = new HashSet<>();authorities1.add("admin");//增加来宾权限Set<String> authorities2 = new HashSet<>();authorities2.add("guest");users.put("admin",new User(1,"admin","123",authorities1));users.put("guest",new User(2,"guest","111",authorities2));}
}

2.3登录成功后,将用户放到session中

import com.dashi.security.model.AuthenticationRequest;
import com.dashi.security.model.User;
import com.dashi.security.service.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpSession;@Controller
public class LoginController {@Autowiredprivate AuthenticationService authenticationService;@GetMapping("/login")public String login(){return "login";}@PostMapping(value = "/login",produces = {"text/plain;charset=UTF-8"})public String login(AuthenticationRequest authenticationRequest, Model model, HttpSession session){System.out.println("111"+authenticationRequest);User user = authenticationService.authentication(authenticationRequest);session.setAttribute(User.LOGIN_USER,user);String loginMsg = user.getUsername()+"登录成功";System.out.println(loginMsg);model.addAttribute("loginMsg",loginMsg);return "loginsuccess";}
}

2.4 增加Springboot拦截器配置,判断是admin用户,可以访问所有资源resource1和resource2,如果是guest用户只允许访问resource2资源

import com.dashi.security.model.User;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@Component
public class MyAuthenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {Object object = request.getSession().getAttribute(User.LOGIN_USER);System.out.println("object = " + object);if(object == null){writeContent(response,"请登录");}//获取请求的urlString requestURI = request.getRequestURI();User user = (User)object;if(user.getAuthorities().contains("admin") && requestURI.contains("/resource1") || requestURI.contains("/resource2")){writeContent(response,user.getUsername()+"访问:"+requestURI+"访问成功!");return true;}if(user.getAuthorities().contains("guest") && requestURI.contains("/resource2")){writeContent(response,user.getUsername()+"访问:"+requestURI+"访问成功!");return true;}writeContent(response,"权限不足!");return false;}private void writeContent(HttpServletResponse response,String msg) throws IOException {response.setContentType("text/html;charset=utf-8");PrintWriter printWriter = response.getWriter();printWriter.write(msg);printWriter.close();response.resetBuffer();}
}

2.5 创造拦截器进行请求拦截,拦截/resource/**请求

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration
public class LoginConfig implements WebMvcConfigurer {@Autowiredprivate MyAuthenInterceptor myAuthenInterceptor;public void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(myAuthenInterceptor).addPathPatterns("/resource/**");}
}

2.7 授权测试界面如下:

  • 登录成功后设置resource1和resource2访问功能

  • admin用户访问资源1和资源2

  • guest用户只能访问资源2,不能访问资源1

2.8 对比springsecurity的认证和授权

1、 认证功能:
loginPage("/login.html")即为认证
2、 授权功能:
.antMatchers("/resource/resource1").hasAuthority(“admin”)
.antMatchers("/resource/resource2").hasAuthority(“admin”)
.antMatchers("/resource/resource2").hasAuthority(“guest”)

  @Overrideprotected void configure(HttpSecurity http) throws Exception {//以下五步是表单登录进行身份认证最简单的登录环境http.formLogin() //表单登陆.loginPage("/login.html") //指定登陆页面.loginProcessingUrl("/authentication/form")//登陆页面提交的页面 开始使用UsernamePasswordAuthenticationFilter过滤器处理请求.and() //.authorizeRequests() //下面的都是授权的配置                                                   .antMatchers("/resource/resource1").hasAuthority("admin")                                 .antMatchers("/resource/resource2").hasAuthority("admin")                                           .antMatchers("/resource/resource2").hasAuthority("guest")    .and().csrf().disable();//关闭跨站请求伪造攻击拦截

手撸一个springsecurity,了解一下security原理相关推荐

  1. 很多小伙伴不太了解ORM框架的底层原理,这不,冰河带你10分钟手撸一个极简版ORM框架(赶快收藏吧)

    大家好,我是冰河~~ 最近很多小伙伴对ORM框架的实现很感兴趣,不少读者在冰河的微信上问:冰河,你知道ORM框架是如何实现的吗?比如像MyBatis和Hibernate这种ORM框架,它们是如何实现的 ...

  2. .Net Core手撸一个基于Token的权限认证

    说明 权限认证是确定用户身份的过程.可确定用户是否有访问资源的权力 今天给大家分享一下类似JWT这种基于token的鉴权机制 基于token的鉴权机制,它不需要在服务端去保留用户的认证信息或者会话信息 ...

  3. javascript实现图片轮播_手撸一个简易版轮播图(上)

    手撸一个简易版轮播图 实现原理,通过控制 swiper-warpper 容器的定位来达到切换图片的效果. 页面布局 简易版轮播图 < > 页面样式 .container{width: 60 ...

  4. Goroutine 并发调度模型深度解析之手撸一个高性能 goroutine 池

    文章目录 1 前言 2 Goroutine & Scheduler 2.1 线程那些事儿 2.1.1 用户级线程模型 2.1.2 内核级线程模型 2.1.3 两级线程模型 2.2 G-P-M ...

  5. 五分钟,手撸一个Spring容器!

    Spring是我们最常用的开源框架,经过多年发展,Spring已经发展成枝繁叶茂的大树,让我们难以窥其全貌. 这节,我们回归Spring的本质,五分钟手撸一个Spring容器,揭开Spring神秘的面 ...

  6. php 六边形 属性图 能力数值图,详解基于 Canvas 手撸一个六边形能力图

    一.前言 六边形能力图如下,由 6 个 六边形组成,每一个顶点代表其在某一方面的能力.这篇文章我们就来看看如何基于 canvas 去绘制这么一个六边形能力图.当然,你也可以基于其他开源的 js 方案来 ...

  7. 使用Node.js手撸一个建静态Web服务器,内部CV指南

    文章里有全部代码,也可以积分下载 操作步骤如上图 文章结束 话说这个键盘真漂亮~~ 文章目录 使用Node.js手撸一个建静态Web服务器 一.动静态服务器的概念 1.1 静态Web服务器概念 1.2 ...

  8. 10分钟手把手教你用Android手撸一个简易的个人记账App

    用Android手撸一个简易的个人记账系统 ⛱️序言

  9. 呆呆带你手撸一个思维导图-基础篇

    希沃ENOW大前端 公司官网:CVTE(广州视源股份) 团队:CVTE旗下未来教育希沃软件平台中心enow团队 「本文作者:」 前言 你盼世界,我盼望你无bug.Hello 大家好,我是霖呆呆! 哈哈 ...

最新文章

  1. AutoIt脚本在做自动化操作的时候,如何进行错误捕获?
  2. python学习(二十三) String(下) 分片和索引
  3. CentOS 5.3 下快速安装配置 PPTP ××× 服务器
  4. “泡泡玛特乐园”,难逃IP大考
  5. android 键盘点击事件监听事件,Android 键盘事件触发以及监听
  6. 训练日志 2019.2.10
  7. 【干货】美团大脑系列之商品知识图谱的构建及应用.pdf(附下载链接)
  8. Python 推导式(列表推导式,字典推导式,集合推导式)
  9. iterator接口
  10. 使用XMAPP启动MySQL出现Error MySQL shutdown unexpectedly 的解决办法
  11. 分享一个我常用的信息差赚钱渠道
  12. Word2019添加复选框
  13. android动画入门
  14. linux yum用法,Linux系统yum的使用与说明
  15. 算法 代码拷来终觉浅,绝知此事要躬行
  16. 常州2021高考成绩查询,2021江苏常州高考选课分班情况(数据)
  17. 移动端适配之一:到底什么是像素
  18. 动手深度学习13——计算机视觉:数据增广、图片分类
  19. STM32F103VE基于标准库下DHT11数据串口打印输出
  20. 统信软件宣布旗下深度社区全新规划 打造我国主导的全球桌面系统根社区

热门文章

  1. 制作ARM的Linux,手工制作最新版arm-linux交叉工具链1.doc
  2. Servlet5.0规范英文版
  3. Kernel:性能分析实例(一)
  4. AWR 分析 :独上高楼,望见 AWR 路
  5. python中使用scipy.optimize.leastsq进行球面、圆柱面、平面拟合
  6. redis5集群安装并设置密码
  7. 中国软件业的现状浅析
  8. leetCode:121\122\309 股票买入和卖出获取最大收益问题
  9. 用于高NA显微镜成像的工程化PSF
  10. 实况足球2020服务器维护时间,实况足球手游-2020开服表