1.前言

前面学习了 security的登录与登出 , 但是用户信息 是 application 配置 或内存直接注入进去的 ,不具有实用性,实际上的使用还需要权限管理,有些 访问接口需要某些权限才可以使用

于是多了个权限管理的问题

2.环境

spring boot 2.1.6.RELEASE

mysql 5.5.28*win64

jdk 1.8.0_221

3.操作

(1)准备一张MySQL表

CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键,自递增',
`username` varchar(20) DEFAULT NULL COMMENT '用户名',
`psw` varchar(140) DEFAULT NULL COMMENT '密码',
`nickname` varchar(50) DEFAULT NULL COMMENT '别名',
`role` varchar(100) DEFAULT NULL COMMENT '权限名',
`setTime` datetime DEFAULT NULL COMMENT '注册时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4;

(2)目录结构

(3)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.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>security-5500</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>security-5500</name>
<description>Demo project for Spring Boot</description> <properties>
<!-- 设置项目编码格式-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties> <dependencies>
<!--spring security 依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</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>
<!-- MySQL 依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- <scope>runtime</scope>-->
<version>5.1.30</version>
</dependency>
<!--MySQL 数据源 依赖包-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency> <!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<!-- mybatis的逆向工程依赖包-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- SCryptPasswordEncoder 加密才需要使用-->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.64</version>
</dependency>
<!--java工具包-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

(4)配置mybatis 与 dao层接口【具体操作这里不演示,可看我的其他随笔有具体讲解】

(5)配置前端页面

index.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
你好 ,世界 ,2333
<p>点击 <a th:href="@{/home}">我</a> 去home.html页面</p> </body>
</html>

home.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="UTF-8">
<title>security首页</title>
</head>
<body>
<h1>Welcome!你好,世界</h1> <p>Click <a th:href="@{/hai}">here</a> to see a greeting.</p>
</body>
</html>

hai.html

<!DOCTYPE html>
<html lang="zh" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="UTF-8">
<title>hai文件</title>
</head>
<body>
你好呀世界,成功登录进来了
<br>
<hr>
用户名:<span th:text="${username}"></span>
<hr>
<!-- 登出 路径是在security 拦截规则 那 设置的 ,当然也可以使用自己写的 ,必须post方式才可以访问,因为默认开启了CSRF -->
<form th:action="@{/mylogout}" method="post">
<button class="btn btn-danger" style="margin-top: 20px">退出登录</button>
</form>
</body>
</html>

kk.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>kk</title>
</head>
<body>
<img src="img/xx.png" alt="">
</body>
</html>

login.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Spring Security自定义</title>
</head>
<body>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div><label> User Name : <input type="text" name="username"/> </label></div>
<div><label> Password: <input type="password" name="password"/> </label></div>
<div><input type="submit" value="Sign In"/></div>
</form>
<br>
lalallalalal啊是德国海
</body>
</html>

(6)配置controller 虚拟路径 【访问接口】

package com.example.security5500.controller;

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView; import java.security.Principal; @Controller
public class MVCController { @RequestMapping("/home")
public String home() {
return "home";
} @RequestMapping("/login")
public String login(){
return "login";
} @RequestMapping("/hai")
public String hai(@AuthenticationPrincipal Principal principal, Model model) {
//获取登录用户名信息 ,如果没有登录 principal.getName() 会报异常,因此弄个异常抛出
String s= "r";
try {
if (principal.getName() !=null){
s = principal.getName();
}
}catch (Exception e){
System.out.println("principal.getName()出异常");
} model.addAttribute("username", s);
return "hai";
} @RequestMapping({"/", "/index"})
public String index() {
return "index";
} @RequestMapping("kk")
public String kk() {
return "kk";
} //获取用户权限
@RequestMapping({"/info"})
@ResponseBody
public Object info(@AuthenticationPrincipal Principal principal) {
return principal;
}
/*
{"authorities":[{"authority":"admin"},{"authority":"user"}],
"details":{"remoteAddress":"0:0:0:0:0:0:0:1","sessionId":"1F57B8E39C5D1DB1F875D57D533DB982"},
"authenticated":true,"principal":{"password":null,"username":"xi","authorities":[{"authority":"admin"},
{"authority":"user"}],"accountNonExpired":true,"accountNonLocked":true,
"credentialsNonExpired":true,"enabled":true},"credentials":null,"name":"xi"} */ }
package com.example.security5500.controller;

import com.example.security5500.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.Principal;
import java.util.Map; @Controller
@RequestMapping("/admin")
public class UserController { @Autowired
private UserService userService; // //登出操作
// @RequestMapping({"/lo"})
// public String logout(HttpServletRequest request, HttpServletResponse response) {
// Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// if (auth != null) {//清除认证
// new SecurityContextLogoutHandler().logout(request, response, auth);
// }
// //重定向到指定页面
// return "redirect:/login";
// } //添加用户
@RequestMapping({"/addUser"})
@ResponseBody
public Map<String,Object> addUser(String username , String psw ) {
return userService.addUser(username,psw);
} }

(7)service层实现类

package com.example.security5500.service.serviceImpl;

import com.example.security5500.dao.TUserMapper;
import com.example.security5500.entitis.tables.TUser;
import com.example.security5500.service.UserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service; import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.Map; @Service
public class UserServiceImpl implements UserService { @Resource
private TUserMapper tUserMapper; //根据用户名获取用户信息
@Override
public TUser getByUsername(String useranme) {
return tUserMapper.selectByUsername(useranme);
} //添加新用户
@Override
public Map<String,Object> addUser(String username, String psw) {
Map<String,Object> map = new HashMap<>();
if (StringUtils.isBlank(username) || StringUtils.isBlank(psw))
{
map.put("data","参数不可空");
return map;
} ////根据用户名获取用户信息
TUser u = tUserMapper.selectByUsername(username);
if (u!= null){
map.put("data","用户名已经存在");
return map;
}
//
TUser tUser = new TUser();
tUser.setUsername(username);
//
//BCryptPasswordEncoder 单向加密
tUser.setPsw((new BCryptPasswordEncoder()).encode(psw));
//
tUser.setNickname("别名-昵称");
tUser.setRole("user");
tUser.setSettime(new Date());
int len = tUserMapper.insertSelective(tUser);
if (len!=1){
map.put("data","失败");
}else {
map.put("data","成功");
}
return map;
}
}

(8)启动类

package com.example.security5500;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.web.servlet.config.annotation.EnableWebMvc; @SpringBootApplication
//设置mapper接口包位置
@MapperScan(basePackages = "com.example.security5500.dao")
public class Security5500Application { public static void main(String[] args) {
SpringApplication.run(Security5500Application.class, args);
} }

(9)security配置类 ,继承了 WebSecurityConfigurerAdapter  ,重写了父类方法 ,可对访问路径自定义设置拦截规则

package com.example.security5500.securityConfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component; //这个加不加无所谓
//@Configuration
//开启security自定义配置
@EnableWebSecurity
//开启 Controller层的访问方法权限,与注解@PreAuthorize("hasRole('admin')")配合,但是 经测试,无法使用,前端访问指定接口报错403 ,
//@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //实例自定义登录校验接口 【内部有 数据库查询】
@Autowired
private DbUserDetailsService dbUserDetailsService; //拦截规则设置
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//允许基于使用HttpServletRequest限制访问
.authorizeRequests()
//设置不拦截页面,可直接通过,路径访问 "/", "/index", "/home" 则不拦截, .antMatchers("/", "/index", "/home", "/hhk/**")
//是允许所有的意思
.permitAll()
//访问 /hai 需要admin权限 ,无权限则提示 403
.antMatchers("/hai").hasAuthority("admin")
//访问 /kk 需要admin或user权限 ,无权限则提示 403
.antMatchers("/kk").hasAnyAuthority("admin","user")
//路径/admin/**所有的请求都需要admin权限 ,无权限则提示 403
.antMatchers("/admin/**").hasAuthority("admin")
//其他页面都要拦截,【需要在最后设置这个】
.anyRequest().authenticated()
.and()
//设置自定义登录页面
.formLogin()
//指定自定义登录页面的访问虚拟路径
.loginPage("/login")
.permitAll()
.and()
// 添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效
// 来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
.logout()
// //指定的登出操作的虚拟路径,需要以post方式请求这个 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用户认证信息达到登出目的
.logoutUrl("/mylogout")
//登出成功后访问的地址
.logoutSuccessUrl("/home");
} /**
* 添加 UserDetailsService, 实现自定义登录校验,数据库查询
*/
@Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
//注入用户信息,每次登录都会来这查询一次信息,因此不建议每次都向mysql查询,应该使用redis
//密码加密
builder.userDetailsService(dbUserDetailsService).passwordEncoder(passwordEncoder());
} /**
* BCryptPasswordEncoder相关知识:
* 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。
* 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。
* BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。
*/
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} // /**
// * 选择加密方式 ,密码不加密的时候选择 NoOpPasswordEncoder,不可缺少,否则报错
// * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
// */
// @Bean
// public static PasswordEncoder passwordEncoder() {
// return NoOpPasswordEncoder.getInstance();
// } }

(10)实现自定义登录校验,实现了根据用户名去数据库查询用户信息,集齐参数用户名、加密后的密码、权限 ,

然后使用 new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities); 注册登录用户 ,

然后内部会自动对比密码 进行校验 【使用 BCryptPasswordEncoder 单项加密】

package com.example.security5500.securityConfig;

import com.example.security5500.entitis.tables.TUser;
import com.example.security5500.service.UserService;
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 java.util.ArrayList;
import java.util.List; @Service
public class DbUserDetailsService implements UserDetailsService { @Autowired
private UserService userService; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名查询用户信息
TUser tUser = userService.getByUsername(username);
if (tUser == null){
throw new UsernameNotFoundException("用户不存在!");
}
//权限设置
// List<GrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
String role = tUser.getRole();
//分割权限名称,如 user,admin
String[] roles = role.split(",");
System.out.println("添加权限");
for (String r :roles){
System.out.println(r);
//添加权限
simpleGrantedAuthorities.add(new SimpleGrantedAuthority(r));
} // simpleGrantedAuthorities.add(new SimpleGrantedAuthority("USER"));
/**
* 创建一个用于认证的用户对象并返回,包括:用户名,密码,角色
*/
//输入参数
return new org.springframework.security.core.userdetails.User(tUser.getUsername(), tUser.getPsw(), simpleGrantedAuthorities);
} }

(11)application.properties

spring.application.name=security-5500
# 应用服务web访问端口
server.port=5500
#配置security登录账户密和密码 ,不配置则默认账户是user,密码是随机生成的字符串,打印在启动栏中
#spring.security.user.name=11
#spring.security.user.password=22
#
##
##
##
## Enable template caching.
#spring.thymeleaf.cache=true
## Check that the templates location exists.
#spring.thymeleaf.check-template-location=true
## Content-Type value.
##spring.thymeleaf.content-type=text/html
## Enable MVC Thymeleaf view resolution.
#spring.thymeleaf.enabled=true
## Template encoding.
#spring.thymeleaf.encoding=utf-8
## Comma-separated list of view names that should be excluded from resolution.
#spring.thymeleaf.excluded-view-names=
## Template mode to be applied to templates. See also StandardTemplateModeHandlers.
#spring.thymeleaf.mode=HTML5
## Prefix that gets prepended to view names when building a URL.
##设置html文件位置
#spring.thymeleaf.prefix=classpath:/templates/
## Suffix that gets appended to view names when building a URL.
#spring.thymeleaf.suffix=.html spring.thymeleaf.template-resolver-order=
# Order of the template resolver in the chain. spring.thymeleaf.view-names= # Comma-separated list of view names that can be resolved.
#
#
#设置mybatis
#mybatis设置
#mybatis配置文件所在路径
mybatis.config-location=classpath:mybatis/config/mybatisConfig.xml
#所有Entity别名类所在包
mybatis.type-aliases-package=com.example.security5500.entitis.tables
#mapper映射xml文件[也可以放在 resources 里面]
#不论放在哪里,都必须使用classpath: 否则找不到 ,报错 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
mybatis.mapper-locations= classpath:mybatis/mapper/**/*.xml #mysql配置
# 当前数据源操作类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# mysql驱动包
spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver
# 数据库名称
spring.datasource.url=jdbc:mysql://localhost:3306/security?characterEncoding=utf-8
# 数据库账户名
spring.datasource.username=root
# 数据库密码
spring.datasource.password=mysql
#
#
# 数据库连接池的最小维持连接数
spring.datasource.dbcp2.min-idle=5
# 初始化连接数
spring.datasource.dbcp2.initial-size=5
# 最大连接数
spring.datasource.dbcp2.max-total=5
# 等待连接获取的最大超时时间
spring.datasource.dbcp2.max-wait-millis=200
#
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个,
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
spring.datasource.druid.test-on-borrow=false
#
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
spring.datasource.druid.test-while-idle=true
#
# 指明是否在归还到池中前进行检验,注意: 设置为true后如果要生效,
#validationQuery参数必须设置为非空字符串
spring.datasource.druid.test-on-return=false
#
# SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.
#如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录
spring.datasource.druid.validation-query=select 1

4.测试

(1)启动 默认进入 index.html

点击 “我” ,进入 home.html

点击 “here”  ,进入 hai.html ,但是因为设置了拦截,需要登录才可以访问 ,因此进入了自定义的登录页面

用一个只有 user权限的账户

username = cen

password = 11

登录后显示 403

因为我将访问 hai.html的权限设为需要 admin 才可以访问 ,因此拒绝操作

换一个有admin权限的账户

username = xi

password = 11

访问网址http://localhost:5500/login

再次登录

这是对一个终端访问接口的权限拦截

那么,需要将某一路径的请求都给拦截怎么办?难道一个一个写?

不,可以拦截上一层的虚拟路径

security的的配置写法

(2)一个拦截路径可以设置多个权限,只要有任意一个权限都可以访问

网址访问 http://localhost:5500/kk  ,【无权限仍然提示403】

spring security +MySQL + BCryptPasswordEncoder 单向加密验证 + 权限拦截 --- 心得的更多相关文章

  1. 基于spring security 实现前后端分离项目权限控制

    前后端分离的项目,前端有菜单(menu),后端有API(backendApi),一个menu对应的页面有N个API接口来支持,本文介绍如何基于spring security实现前后端的同步权限控制. ...

  2. Spring Security教程之基于方法的权限控制(十二)

    目录 1.1     intercept-methods定义方法权限控制 1.2     使用pointcut定义方法权限控制 1.3     使用注解定义方法权限控制 1.3.1    JSR-25 ...

  3. vue路由守卫用于登录验证权限拦截

    vue路由守卫用于登录验证权限拦截 vue路由守卫 - 全局(router.beforeEach((to, from, next) =>来判断登录和路由跳转状态) 主要方法: to:进入到哪个路 ...

  4. spring security的BCryptPasswordEncoder加密和对密码验证的原理

    目录 BCryptPasswordEncoder加密和对密码验证的原理 一.加密算法和hash算法的区别 二.源码解析 1. encode方法 2. BCrypt.hashpw方法 3. matche ...

  5. spring boot:spring security整合jwt实现登录和权限验证(spring boot 2.3.3)

    一,为什么使用jwt? 1,什么是jwt? Json Web Token, 它是JSON风格的轻量级的授权和身份认证规范, 可以实现无状态.分布式的Web应用授权 2,jwt的官网: https:// ...

  6. springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  7. 255.Spring Boot+Spring Security:使用md5加密

    说明 (1)JDK版本:1.8 (2)Spring Boot 2.0.6 (3)Spring Security 5.0.9 (4)Spring Data JPA 2.0.11.RELEASE (5)h ...

  8. 【Spring Security】二、数据库管理用户权限

    一 引入相关的jar包 这个例子用的是mysql数据库和c3p0开源的jdbc连接池,在项目的pom.xml中引入jar包 <!-- Mysql --> <dependency> ...

  9. Spring Security + JWT实现前后端分离权限认证

    现在国内前后端很多公司都在使用前后端分离的开发方式,虽然也有很多人并不赞同前后端分离,比如以下这篇博客就很有意思: https://www.aliyun.com/jiaocheng/650661.ht ...

随机推荐

  1. 6.Vue.js-条件与循环

    条件判断 v-if 条件判断使用 v-if 指令: <div id="app"> <p v-if="seen">现在你看到我了</ ...

  2. 【阿菜做实践】利用ganache-cli本地fork以太坊主链分叉

    前言 Fork主网意思是模拟具有与主网相同的状态的网络,但它将作为本地开发网络工作. 这样你就可以与部署的协议进行交互,并在本地测试复杂的交互.不用担心分叉主网作为测试链会占很多内存.这些方法都不会将 ...

  3. 「Python实用秘技02」给Python函数定“闹钟”

    本文完整示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/PythonPracticalSkills 这是我的系列文章「Python实用秘技」的第2期 ...

  4. Linux的命令行基础

    1.对于全局配置文件和用户配置文件的认识 全局配置都存储在etc目录下,如/etc/profile文件,/etc/bashrc文件以及/etc/profile.d/目录下的.sh文件 用户配置都存储在 ...

  5. sctf_2019_easy_heap(off-by-null在2.27的利用)

    题目的例行检查我就不放了 将程序放入ida中 漏洞也较为明显 可以看到 if这里多一个null ,明显的off by null 漏洞 程序在最开始的地方给了我们一个很大的空间,并且权限是rwx,所以我 ...

  6. [BUUCTF]PWN——bjdctf_2020_babyrop2

    bjdctf_2020_babyrop2 附件 步骤: 例行检查,64位程序,开启了NX和canary保护 2. 试运行一下程序,看看大概的情况 提示我们去泄露libc 3. 64位ida载入,从ma ...

  7. Windows 10 彻底关闭 Antimalware Service Executable 降低内存占用

    概述 最近给内网的一台电脑安装 Windows 10 专业版系统,由于此电脑不会涉及到不安全因素,所以杀毒软件非必须. 以最大限度节省系统资源考虑,默认安装的 Micoroft Defender 占用 ...

  8. Vue页面内公共的多类型附件图片上传区域并适用折叠面板

    在前端项目中,附件上传是很常用的功能,几乎所有的app相关项目中都会使用到,一般在选择使用某个前端UI框架时,可以查找其内封装好的图片上传组件,但某些情况下可能并不适用于自身的项目需求,本文中实现的附 ...

  9. JAVA获取当前日期所在的周一到周日的所有日期集合

    /** * 获取当前日期所在的周一到周日的所有日期集合 * @return */ public static List<Date> getWeekDateList() { Calendar ...

  10. 【LeetCode】42. Trapping Rain Water 接雨水 (C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力求解 保存左右最大值 单调栈 日期 题目地址:ht ...