【Spring Security】入门——使用Themeleaf渲染页面
- 一、项目框架
- 1. 项目结构
- 2. 选择依赖
- 二、数据库
- 三、代码实现
- 实现思路
- 1. 配置文件
- 2. 编写测试页面
- index.html
- login.html
- register.html
- 3. 配置视图访问器
- 4. 进行Spring Security配置
- 5. 编写dao层和mapper文件
- 6. 编写service层
- 7. 编写controller层
- 附:实体类与帮助类
技术点:
- Spring Boot
- Spring Security
- MySQL
- MyBatis
- Thymeleaf
本项目GitHub传送门
一、项目框架
1. 项目结构
2. 选择依赖
使用Spring Boot 创建项目。
依赖勾选
- Spring Boot DevTools
- Spring Web
- Spring Security
- Thymeleaf
- Mybatis Framework
- MySQL Driver
可参考此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.3.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.aaa</groupId><artifactId>springboot-security-thymeleaf</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot-security-thymeleaf</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-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></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>
二、数据库
共5张表
- t_user 用户表
- t_role 角色表
- r_user_role 用户-角色
- r_permission 权限表
- r_role_permission 角色-权限
/*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50610Source Host : localhost:3306Source Schema : user_dbTarget Server Type : MySQLTarget Server Version : 50610File Encoding : 65001Date: 21/07/2020 21:29:29
*/SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`code` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '权限标识符',`description` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',`url` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '请求地址',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', 'p1', '测试资源1', '/resource/r1');
INSERT INTO `t_permission` VALUES ('2', 'p2', '测试资源2', '/resource/r2');
INSERT INTO `t_permission` VALUES ('3', 'p3', '测试资源3', '/resource/r3');-- ----------------------------
-- Table structure for t_role
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`role_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`create_time` datetime(0) NULL DEFAULT NULL,`update_time` datetime(0) NULL DEFAULT NULL,`status` char(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `unique_role_name`(`role_name`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', NULL, NULL, NULL, '');-- ----------------------------
-- Table structure for t_role_permission
-- ----------------------------
DROP TABLE IF EXISTS `t_role_permission`;
CREATE TABLE `t_role_permission` (`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`permission_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,PRIMARY KEY (`role_id`, `permission_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` VALUES ('1', '1');
INSERT INTO `t_role_permission` VALUES ('1', '2');-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户id',`username` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`password` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`fullname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户姓名',`mobile` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'zhangsan', '$2a$10$37vdSYJUVguwXpLDnZfEt.UDC0y6Yk2RCzFuJKfOrWCiTnUFlmj3K', NULL, NULL);-- ----------------------------
-- Table structure for t_user_role
-- ----------------------------
DROP TABLE IF EXISTS `t_user_role`;
CREATE TABLE `t_user_role` (`user_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`role_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,`create_time` datetime(0) NULL DEFAULT NULL,`creator` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,PRIMARY KEY (`user_id`, `role_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES ('1', '1', NULL, NULL);
SET FOREIGN_KEY_CHECKS = 1;
三、代码实现
实现思路
- 配置Spring Boot环境。将服务器配置、数据源、MyBatis映射文件、启动文件完成配置。
- 完成基本的html(Thymeleaf)页面。用于测试用户注册、登录、访问资源功能。
- 配置html视图器。将使用Thymeleaf中的视图进行配置。
- 进行Spring Security配置。主要配置密码编码器、安全拦截器、登录页面。
- 编写dao层和mapper文件。用于连接数据库。
- 编写service层。一方面是实现用户的注册和登录,另一方面是实现spring-security核心接口,其负载着用户特定数据,它被用来在整个框架作为一个用户DAO。
- 编写controller层。用于页面访问,在controller接口中可以设置接口的访问权限,让Spring Security进行安全验证。
1. 配置文件
application.properties
# web
server.port=8080
server.servlet.context-path=/
spring.application.name=security-springboot
# DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/user_db?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
2. 编写测试页面
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head><meta charset="UTF-8"><title>index</title>
</head>
<body>
登录成功
<h1>菜单页</h1>
<hr>
<h3><a href="/resource/r1" target="_blank">资源一</a></h3>
<h3><a href="/resource/r2" target="_blank">资源二</a></h3>
<h3><a href="/resource/r3" target="_blank">资源三</a></h3><hr>
<form th:action="@{/logout}" method="get" ><button type="submit" >退出</button>
</form></body>
</html>
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head><meta charset="UTF-8"><title>登录</title>
</head>
<body>
<form th:action="@{/loginForm}" method="post" >用户名<input type="text" name="username" /><br>密码<input type="password" name="password" /><br><button type="submit" >提交</button><!-- ${session?.SPRING_SECURITY_LAST_EXCEPTION?.message} security自带的错误提示信息 --><p th:if="${param.error}" th:text="${session?.SPRING_SECURITY_LAST_EXCEPTION?.message}" ></p>
</form>
<a th:href="@{/register}">注册</a>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>注册</title>
</head>
<body>
<h1>注册</h1>
<form action="/user/register" method="post">用户名:<input type="text" name="username"><br>密码:<input type="password" name="password"><br><input type="submit" value="注册">
</form>
<hr>
<p><a href="/">登录</a></p>
</body>
</html>
3. 配置视图访问器
htmlController
package com.aaa.springbootsecuritythymeleaf.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;/*** @author 淮南King* @date 2020-08-04*/
@RestController
public class htmlController {@RequestMapping("/index")public ModelAndView index(){return new ModelAndView("/index");}@RequestMapping("/test")public Object test(){return "test 此请求无需权限";}/*** 自定义登录页面* @param error 错误信息显示标识* @return**/@GetMapping("/login")public ModelAndView login(String error){ModelAndView modelAndView = new ModelAndView("/login");modelAndView.addObject("error", error);return modelAndView;}/*** 自定义注册页面* @return**/@RequestMapping("/register")public ModelAndView register(){return new ModelAndView("register");}
}
4. 进行Spring Security配置
WebSecurityConfig
package com.aaa.springbootsecuritythymeleaf.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;/*** spring security配置** @author 淮南King*/
@Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfigextends WebSecurityConfigurerAdapter {//密码编码器@Bean public PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//安全拦截机制@Override protected void configure(HttpSecurity http) throws Exception {http.csrf().disable()//允许表单登录.formLogin()//登录页面路径.loginPage("/login").loginProcessingUrl("/loginForm")//设置登录成功跳转页面,error=true控制页面错误信息的展示.successForwardUrl("/index").failureUrl("/login?error=true").permitAll().and()//允许不登陆就可以访问的方法,多个用逗号分隔.authorizeRequests().antMatchers("/test","/user/**","/register").permitAll()//其他的需要授权后访问.anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().logout()//登录退出.logoutUrl("/logout")//退出时情况cookies.and().logout().deleteCookies("JESSIONID").logoutSuccessUrl("/login?logout");}
}
MyUserDetail
package com.aaa.springbootsecuritythymeleaf.config;import com.aaa.springbootsecuritythymeleaf.dao.UserDao;
import com.aaa.springbootsecuritythymeleaf.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
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.List;/*** 实现spring-security核心接口,其负载的用户特定数据。** @author 淮南King*/
@Service
public class MyUserDetail implements UserDetailsService {@Autowired UserDao userDao;// 根据账号查询用户信息@Override public UserDetails loadUserByUsername(String username) {//将来连接数据库根据账号查询用户信息User userDto = userDao.getUserByUsername(username);//当查询此用户不存在时,将抛出用户名未找到异常if (userDto == null) {throw new UsernameNotFoundException("No such user found, the user name is: "+username);}//根据用户id查询权限List<String> permissions = userDao.findPermissionsByUserId(userDto.getId());//将permissions转为数组String[] permissionArray = new String[permissions.size()];permissions.toArray(permissionArray);UserDetails userDetails =org.springframework.security.core.userdetails.User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray).build();return userDetails;}
}
5. 编写dao层和mapper文件
UserDao.java
package com.aaa.springbootsecuritythymeleaf.dao;import com.aaa.springbootsecuritythymeleaf.entity.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** 用户信息持久层* @author 淮南King*/
@Mapper
public interface UserDao {/*** 根据账号查询用户信息** @param username 用户姓名* @return 用户信息*/User getUserByUsername(String username);/*** 根据用户id查询用户权限** @param userId 用户id* @return 权限列表*/List<String> findPermissionsByUserId(String userId);/*** 添加用户** @param userDTO 用户信息* @return 修改条数*/int addUser(User userDTO);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.aaa.springbootsecuritythymeleaf.dao.UserDao"><select id="getUserByUsername" parameterType="String" resultType="com.aaa.springbootsecuritythymeleaf.entity.User">select id,username,password,fullname,mobile from t_user where username = #{username}</select><select id="findPermissionsByUserId" parameterType="String" resultType="String">SELECT code FROM t_permission WHERE id IN(SELECT permission_id FROM t_role_permission WHERE role_id IN(SELECT role_id FROM t_user_role WHERE user_id = #{id} ))</select><insert id="addUser" parameterType="com.aaa.springbootsecuritythymeleaf.entity.User">INSERT INTO `user_db`.`t_user`(`username`, `password`) VALUES (#{username},#{password})</insert>
</mapper>
6. 编写service层
UserService
package com.aaa.springbootsecuritythymeleaf.service;import com.aaa.springbootsecuritythymeleaf.dao.UserDao;
import com.aaa.springbootsecuritythymeleaf.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;import java.util.List;/*** 用户信息持久业务层** @author 淮南King* @date 2020-07-21*/
@Service
public class UserService {@Autowired UserDao dao;public User getUserByUsername(String username) {return dao.getUserByUsername(username);}public List<String> findPermissionsByUserId(String userId) {return dao.findPermissionsByUserId(userId);}/*** 添加用户* @param user* @return*/public int addUser(User user) {//获取密码编码器PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();//将用户的密码进行编码String password = passwordEncoder.encode(user.getPassword());//将编码后的密码覆盖到用户信息中user.setPassword(password.substring(8));//将用户信息持久化到数据库中return dao.addUser(user);}
}
7. 编写controller层
LoginController
package com.aaa.springbootsecuritythymeleaf.controller;import com.aaa.springbootsecuritythymeleaf.entity.User;
import com.aaa.springbootsecuritythymeleaf.service.UserService;
import com.aaa.springbootsecuritythymeleaf.util.SecurityUtil;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;/*** @author 淮南King*/
@RestController
public class LoginController {@Resource private UserService service;@RequestMapping(value = "/login-success",produces = {"text/plain;charset=UTF-8"})public ModelAndView loginSuccess(){//获取当前线程的SecurityContextAuthentication authentication = SecurityContextHolder.getContext().getAuthentication();//获取当前线程中用户的名称,将名称传递至页面Map<String,Object> attributes = new HashMap<>();attributes.put("username", SecurityUtil.getUserNameByAuthentication(authentication));return new ModelAndView("menu",attributes);}@PostMapping("/user/register")public String register(User user) {service.addUser(user);return user.getUsername()+"注册成功";}@GetMapping("/register")public ModelAndView registerView() {return new ModelAndView("register");}}
AuthController
package com.aaa.springbootsecuritythymeleaf.controller;import com.aaa.springbootsecuritythymeleaf.util.SecurityUtil;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author 淮南King* @date 2020-07-21*/
@RestController
@RequestMapping("/resource")
public class AuthController {/*** 测试资源1* 拥有p1权限才可以访问** @return*/@GetMapping(value = "/r1", produces = {"text/plain;charset=UTF-8"})@PreAuthorize("hasAuthority('p1')")public String resource1() {//获取当前线程的SecurityContextAuthentication authentication = SecurityContextHolder.getContext().getAuthentication();//获取当前线程的名称return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源1";}/*** 测试资源2* 拥有p2权限才可以访问** @return*/@GetMapping(value = "/r2", produces = {"text/plain;charset=UTF-8"})@PreAuthorize("hasAuthority('p2')")public String resource2() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源2";}/*** 测试资源3* 拥有p3权限才可以访问** @return*/@GetMapping(value = "/r3", produces = {"text/plain;charset=UTF-8"})@PreAuthorize("hasAuthority('p3')")public String resource3() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();return SecurityUtil.getUserNameByAuthentication(authentication) + " 访问资源3";}
}
附:实体类与帮助类
User
package com.aaa.springbootsecuritythymeleaf.entity;/*** DTO:与数据库保持一致<br>* 用户信息* @author 淮南King*/
public class User {/*** 用户id*/private String id;/*** 用户名*/private String username;/*** 用户密码*/private String password;/*** 用户角色ID*/private Integer roleId;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Integer getRoleId() {return roleId;}public void setRoleId(Integer roleId) {this.roleId = roleId;}
}
Permission
package com.aaa.springbootsecuritythymeleaf.entity;
/*** 权限信息* @author 淮南King*/
public class Permission {/*** 权限id*/private String id;/*** 权限代号*/private String code;/*** 权限描述*/private String description;/*** 路径*/private String url;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}
}
SecurityUtil
package com.aaa.springbootsecuritythymeleaf.util;import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;/*** Security帮助类* @author 淮南King* @date 2020-07-21*/
public class SecurityUtil {/*** 根据当前执行线程的SecurityContext获取用户名称* @param authentication 当前认证通过的用户身份* @return 用户名*/public static String getUserNameByAuthentication(Authentication authentication){String username = null;//用户身份Object principal = authentication.getPrincipal();if(principal == null){return "匿名";}if(principal instanceof UserDetails){UserDetails userDetails = (UserDetails)principal;username = userDetails.getUsername();}else{username = principal.toString();}return username;}
}
项目传送门
end…
【Spring Security】入门——使用Themeleaf渲染页面相关推荐
- Spring Security 入门(五):在 Spring-Boot中的应用
前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖 <parent> <groupId>org.springframework.bo ...
- Spring Security入门到实践(一)HTTP Basic在Spring Security中的应用原理浅析
一.Spring Security简介 打开Spring Security的官网,从其首页的预览上就可以看见如下文字: Spring Security is a powerful and highly ...
- Spring Security入门基础
Spring Security入门基础 文章目录 Spring Security入门基础 一,Spring Security的使用 1.1 基本术语 1.2 基本使用 1.2.1 引入依赖 1.2.2 ...
- 【Spring Security入门】06-QQ登录实现
准备工作 1.在 QQ互联 申请成为开发者,并创建应用,得到APP ID 和 APP Key. 2.了解QQ登录时的 网站应用接入流程.(必须看完看懂) 为了方便各位测试,直接把我自己申请的贡献出来: ...
- Spring Security 入门(四):自定义-Filter
前文导读 - Spring Security入门(一):登录与退出 - Spring Security入门(二):基于数据库验证 - Spring Security入门(三):密码加密 本文解决问题 ...
- Spring Security入门(三):密码加密
前文导读 - Spring Security入门(一):登录与退出 - Spring Security入门(二):基于数据库验证 Github 地址 https://github.com/ChinaS ...
- Spring Security入门01-22 登录验证功能
课程链接:SpringSecurity框架教程 开始时间:2022-07-17 快速入门 搭建一个Spring Boot项目 添加基础依赖和创建启动类和controller controller @R ...
- Spring Boot基础学习笔记20:Spring Security入门
文章目录 零.学习目标 一.Spring Security (一)Spring Security概述 (二)Spring Boot整合Spring Security实现的安全管理功能 二.基础环境搭建 ...
- Spring Security 入门(1-3-2)Spring Security - http元素 - intercept-url配置
http元素下可以配置登录页面,也可以配置 url 拦截. 1.直接配置拦截url和对应的访问权限 <security:http use-expressions="false" ...
最新文章
- Python 图像处理 | 图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
- Python字符串居然可以这样玩 到底怎么做到的 年薪50w程序员揭晓
- 边工作边刷题:70天一遍leetcode: day 97-1
- 用深度优先搜索解迷宫问题
- paho mqtt client调试记录
- java lock unlock_详解Java中的ReentrantLock锁
- hashMap put方法 第二行代码
- pytorch 画loss曲线_Pytorch使用tensorboardX可视化。超详细!!!
- 配置的android版本,Android SDK配置(V3.0.0及以上版本)
- 十一游玩新发现(见怪不怪)
- python exec函数 自动代码规范_Python 开发编码规范
- jdbc连接池的数量设置怎么才合适?
- 转发表(MAC表)、ARP表、路由表总结
- DBLE分库分表示例
- Python新手接了第一个副业单子,2小时完成:Python修正excel表格数据
- ssm 微信扫码支付
- 网络与信息安全学习(七)
- 解决Maven通过ojdbc连接Oracle
- ubuntu下开启/禁用笔记本触摸板
- 惊闻同事噩耗,思绪联翩
热门文章
- 面向对象五大原则_1.单一职责原则amp;2.里氏替换原则
- 找准品牌定位,努力称为一个合适的品牌营销人才
- spark-submit Caused by: java.lang.ClassNotFoundException: org.codehaus.jettison.json.JSONObjec
- js 创建书签小工具并实现自动表单填写
- 检查python是否安装成功的命令是_Python 中的pygame安装与配置教程详解
- php 浮点数和整数相乘,科学网—具体计算一下就更清楚啦(附: 整数相乘及数据拟合) - 尤明庆的博文...
- canvas 制作表情包
- ConEmu –带选项卡的Windows控制台模拟器
- 高通camera hal3学习
- 一篇文章带你读懂JSP的使用的理解