• 一、项目框架
    • 1. 项目结构
    • 2. 选择依赖
  • 二、数据库
  • 三、代码实现
    • 实现思路
    • 1. 配置文件
    • 2. 编写测试页面
      • index.html
      • login.html
      • register.html
    • 3. 配置视图访问器
    • 4. 进行Spring Security配置
    • 5. 编写dao层和mapper文件
    • 6. 编写service层
    • 7. 编写controller层
    • 附:实体类与帮助类

技术点:

  1. Spring Boot
  2. Spring Security
  3. MySQL
  4. MyBatis
  5. Thymeleaf

本项目GitHub传送门

一、项目框架

1. 项目结构

2. 选择依赖

使用Spring Boot 创建项目。
依赖勾选

  1. Spring Boot DevTools
  2. Spring Web
  3. Spring Security
  4. Thymeleaf
  5. Mybatis Framework
  6. 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张表

  1. t_user 用户表
  2. t_role 角色表
  3. r_user_role 用户-角色
  4. r_permission 权限表
  5. 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;

三、代码实现

实现思路

  1. 配置Spring Boot环境。将服务器配置、数据源、MyBatis映射文件、启动文件完成配置。
  2. 完成基本的html(Thymeleaf)页面。用于测试用户注册、登录、访问资源功能。
  3. 配置html视图器。将使用Thymeleaf中的视图进行配置。
  4. 进行Spring Security配置。主要配置密码编码器、安全拦截器、登录页面。
  5. 编写dao层和mapper文件。用于连接数据库。
  6. 编写service层。一方面是实现用户的注册和登录,另一方面是实现spring-security核心接口,其负载着用户特定数据,它被用来在整个框架作为一个用户DAO。
  7. 编写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渲染页面相关推荐

  1. Spring Security 入门(五):在 Spring-Boot中的应用

    前言 本文作为入门级的DEMO,完全按照官网实例演示: 项目目录结构 Maven 依赖  <parent>    <groupId>org.springframework.bo ...

  2. Spring Security入门到实践(一)HTTP Basic在Spring Security中的应用原理浅析

    一.Spring Security简介 打开Spring Security的官网,从其首页的预览上就可以看见如下文字: Spring Security is a powerful and highly ...

  3. Spring Security入门基础

    Spring Security入门基础 文章目录 Spring Security入门基础 一,Spring Security的使用 1.1 基本术语 1.2 基本使用 1.2.1 引入依赖 1.2.2 ...

  4. 【Spring Security入门】06-QQ登录实现

    准备工作 1.在 QQ互联 申请成为开发者,并创建应用,得到APP ID 和 APP Key. 2.了解QQ登录时的 网站应用接入流程.(必须看完看懂) 为了方便各位测试,直接把我自己申请的贡献出来: ...

  5. Spring Security 入门(四):自定义-Filter

    前文导读 - Spring Security入门(一):登录与退出 - Spring Security入门(二):基于数据库验证 - Spring Security入门(三):密码加密 本文解决问题 ...

  6. Spring Security入门(三):密码加密

    前文导读 - Spring Security入门(一):登录与退出 - Spring Security入门(二):基于数据库验证 Github 地址 https://github.com/ChinaS ...

  7. Spring Security入门01-22 登录验证功能

    课程链接:SpringSecurity框架教程 开始时间:2022-07-17 快速入门 搭建一个Spring Boot项目 添加基础依赖和创建启动类和controller controller @R ...

  8. Spring Boot基础学习笔记20:Spring Security入门

    文章目录 零.学习目标 一.Spring Security (一)Spring Security概述 (二)Spring Boot整合Spring Security实现的安全管理功能 二.基础环境搭建 ...

  9. Spring Security 入门(1-3-2)Spring Security - http元素 - intercept-url配置

    http元素下可以配置登录页面,也可以配置 url 拦截. 1.直接配置拦截url和对应的访问权限 <security:http use-expressions="false" ...

最新文章

  1. Python 图像处理 | 图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
  2. Python字符串居然可以这样玩 到底怎么做到的 年薪50w程序员揭晓
  3. 边工作边刷题:70天一遍leetcode: day 97-1
  4. 用深度优先搜索解迷宫问题
  5. paho mqtt client调试记录
  6. java lock unlock_详解Java中的ReentrantLock锁
  7. hashMap put方法 第二行代码
  8. pytorch 画loss曲线_Pytorch使用tensorboardX可视化。超详细!!!
  9. 配置的android版本,Android SDK配置(V3.0.0及以上版本)
  10. 十一游玩新发现(见怪不怪)
  11. python exec函数 自动代码规范_Python 开发编码规范
  12. jdbc连接池的数量设置怎么才合适?
  13. 转发表(MAC表)、ARP表、路由表总结
  14. DBLE分库分表示例
  15. Python新手接了第一个副业单子,2小时完成:Python修正excel表格数据
  16. ssm 微信扫码支付
  17. 网络与信息安全学习(七)
  18. 解决Maven通过ojdbc连接Oracle
  19. ubuntu下开启/禁用笔记本触摸板
  20. 惊闻同事噩耗,思绪联翩

热门文章

  1. 面向对象五大原则_1.单一职责原则amp;2.里氏替换原则
  2. 找准品牌定位,努力称为一个合适的品牌营销人才
  3. spark-submit Caused by: java.lang.ClassNotFoundException: org.codehaus.jettison.json.JSONObjec
  4. js 创建书签小工具并实现自动表单填写
  5. 检查python是否安装成功的命令是_Python 中的pygame安装与配置教程详解
  6. php 浮点数和整数相乘,科学网—具体计算一下就更清楚啦(附: 整数相乘及数据拟合) - 尤明庆的博文...
  7. canvas 制作表情包
  8. ConEmu –带选项卡的Windows控制台模拟器
  9. 高通camera hal3学习
  10. 一篇文章带你读懂JSP的使用的理解