security学习笔记
spring security 入门案例
- 创建springboot工程
- 引入依赖
org.springframework.boot
spring-boot-starter-security
2.创建controller
package com.example.springscuritydemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 崔令雨
* @date 2022/5/19 21:24
* @Version 1.0
*/
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping("hello")
public String hello() {
return "hello security";
}
}
- 启动程序访问我们的控制器方法 会弹出下图界面 用户名是 user 密码在控制台输出
修改默认用户名密码
- 在配置文件中配置用户名密码用来覆盖默认配置
spring.security.user.name=root
spring.security.user.password=root
自定义认证资源规则
- 自定义配置类继承 WebSecurityConfigurerAdapter
package com.example.springscuritydemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin();
}
}
自定义登录页面
- 引入pom依赖
org.springframework.boot
spring-boot-starter-thymeleaf
- 创建登录页面
Title
Login
页面所需css
html {
height: 100%;
}
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background: linear-gradient(#141e30, #243b55);
}
.login-box {
position: absolute;
top: 50%;
left: 50%;
width: 400px;
padding: 40px;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, .5);
box-sizing: border-box;
box-shadow: 0 15px 25px rgba(0, 0, 0, .6);
border-radius: 10px;
}
.login-box h2 {
margin: 0 0 30px;
padding: 0;
color: #fff;
text-align: center;
}
.login-box .user-box {
position: relative;
}
.login-box .user-box input {
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #fff;
margin-bottom: 30px;
border: none;
border-bottom: 1px solid #fff;
outline: none;
background: transparent;
}
.login-box .user-box label {
position: absolute;
top: 0;
left: 0;
padding: 10px 0;
font-size: 16px;
color: #fff;
pointer-events: none;
transition: .5s;
}
.login-box .user-box input:focus ~ label,
.login-box .user-box input:valid ~ label {
top: -20px;
left: 0;
color: #03e9f4;
font-size: 12px;
}
.login-box form a {
position: relative;
display: inline-block;
padding: 10px 20px;
color: #03e9f4;
font-size: 16px;
text-decoration: none;
text-transform: uppercase;
overflow: hidden;
transition: .5s;
margin-top: 40px;
letter-spacing: 4px
}
.login-box a:hover {
background: #03e9f4;
color: #fff;
border-radius: 5px;
box-shadow: 0 0 5px #03e9f4,
0 0 25px #03e9f4,
0 0 50px #03e9f4,
0 0 100px #03e9f4;
}
.login-box a span {
position: absolute;
display: block;
}
.login-box a span:nth-child(1) {
top: 0;
left: -100%;
width: 100%;
height: 2px;
background: linear-gradient(90deg, transparent, #03e9f4);
animation: btn-anim1 1s linear infinite;
}
@keyframes btn-anim1 {
0% {
left: -100%;
}
50%, 100% {
left: 100%;
}
}
.login-box a span:nth-child(2) {
top: -100%;
right: 0;
width: 2px;
height: 100%;
background: linear-gradient(180deg, transparent, #03e9f4);
animation: btn-anim2 1s linear infinite;
animation-delay: .25s
}
@keyframes btn-anim2 {
0% {
top: -100%;
}
50%, 100% {
top: 100%;
}
}
.login-box a span:nth-child(3) {
bottom: 0;
right: -100%;
width: 100%;
height: 2px;
background: linear-gradient(270deg, transparent, #03e9f4);
animation: btn-anim3 1s linear infinite;
animation-delay: .5s
}
@keyframes btn-anim3 {
0% {
right: -100%;
}
50%, 100% {
right: 100%;
}
}
.login-box a span:nth-child(4) {
bottom: -100%;
left: 0;
width: 2px;
height: 100%;
background: linear-gradient(360deg, transparent, #03e9f4);
animation: btn-anim4 1s linear infinite;
animation-delay: .75s
}
@keyframes btn-anim4 {
0% {
bottom: -100%;
}
50%, 100% {
bottom: 100%;
}
}
- 关闭thymeleaf缓存
spring.thymeleaf.cache=false
- 定义控制器
package com.example.springscuritydemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author 崔令雨
* @date 2022/5/21 14:48
* @Version 1.0
*/
@Controller
public class LoginController {
@RequestMapping("login.html")
public String login() {
return "login";
}
}
- 设置security配置
package com.example.springscuritydemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.mvcMatchers("/login.html").permitAll()
.mvcMatchers("/login.css").permitAll()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin()
//设置登录页面
.loginPage("/login.html")
.loginProcessingUrl("/login") // 设置验证请求路径
// .successForwardUrl("/test/hello") //验证成功后请求转发到指定页面 请求转发到指定页
//验证成功后默认跳转到第一次发送请求页面
// .defaultSuccessUrl("/index/hello") // 设置默认跳转页面 请求重定向到指定页
.usernameParameter("usern") //设置用户名属性
.passwordParameter("paswd") //设置密码属性
.failureUrl("/index.html")//请求失败后跳转页面
//禁用crsf
.and().csrf().disable();
}
}
错误页面
1. 显示错误信息
1. 创建错误页面
FlexBox Exercise #3 - Image carousel / Responsive
The grand moment
Le tour
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Explore the tour
The big window
Minimal window
Clear Glass Window With Brown and White Wooden Frame iste natus error sit voluptatem accusantium doloremque laudantium.
Read the article
Tropical palms
Palms
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Explore the palms
Beach
The beach
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Explore the beach
The white building
White building
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.
Read the article
2. 错误页面相关css
@import url('https://fonts.googleapis.com/css?family=Playfair+Display:400,400i,700,700i,900,900i');
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i,800,800i');
* {
box-sizing: border-box;
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
display: flex;
display: -webkit-flex;
justify-content: center;
-webkit-justify-content: center;
align-items: center;
-webkit-align-items: center;
}
body {
background-color: #eaeaea;
}
.carousel {
width: 100%;
height: 100%;
display: flex;
max-width: 900px;
max-height: 550px;
overflow: hidden;
position: relative;
}
.carousel-item {
visibility: visible;
display: flex;
width: 100%;
height: 100%;
align-items: center;
justify-content: flex-end;
-webkit-align-items: center;
-webkit-justify-content: flex-end;
position: relative;
background-color: #fff;
flex-shrink: 0;
-webkit-flex-shrink: 0;
position: absolute;
z-index: 0;
transition: 0.6s all linear;
}
.carousel-item__info {
height: 100%;
display: flex;
justify-content: center;
flex-direction: column;
display: -webkit-flex;
-webkit-justify-content: center;
-webkit-flex-direction: column;
order: 1;
left: 0;
margin: auto;
padding: 0 40px;
width: 40%;
}
.carousel-item__image {
width: 60%;
height: 100%;
order: 2;
align-self: flex-end;
flex-basis: 60%;
-webkit-order: 2;
-webkit-align-self: flex-end;
-webkit-flex-basis: 60%;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: relative;
transform: translateX(100%);
transition: 0.6s all ease-in-out;
}
.carousel-item__subtitle {
font-family: 'Open Sans', sans-serif;
letter-spacing: 3px;
font-size: 10px;
text-transform: uppercase;
margin: 0;
color: #7E7E7E;
font-weight: 700;
transform: translateY(25%);
opacity: 0;
visibility: hidden;
transition: 0.4s all ease-in-out;
}
.carousel-item__title {
margin: 15px 0 0 0;
font-family: 'Playfair Display', serif;
font-size: 44px;
line-height: 45px;
letter-spacing: 3px;
font-weight: 700;
color: #2C2C2C;
transform: translateY(25%);
opacity: 0;
visibility: hidden;
transition: 0.6s all ease-in-out;
}
.carousel-item__description {
transform: translateY(25%);
opacity: 0;
visibility: hidden;
transition: 0.6s all ease-in-out;
margin-top: 35px;
font-family: 'Open Sans', sans-serif;
font-size: 13px;
color: #7e7e7e;
line-height: 22px;
margin-bottom: 35px;
}
.carousel-item--1 .carousel-item__image {
background-image: url('https://images.pexels.com/photos/991012/pexels-photo-991012.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940');
}
.carousel-item--2 .carousel-item__image {
background-image: url('https://images.pexels.com/photos/921294/pexels-photo-921294.png?auto=compress&cs=tinysrgb&h=750&w=1260');
}
.carousel-item--3 .carousel-item__image {
background-image: url('https://images.pexels.com/photos/92733/pexels-photo-92733.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260');
}
.carousel-item--4 .carousel-item__image {
background-image: url('https://images.pexels.com/photos/1008732/pexels-photo-1008732.jpeg?auto=compress&cs=tinysrgb&h=750&w=1260');
}
.carousel-item--5 .carousel-item__image {
background-image: url('https://images.pexels.com/photos/1029614/pexels-photo-1029614.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940');
}
.carousel-item__container {
}
.carousel-item__btn {
width: 35%;
color: #2C2C2C;
font-family: 'Open Sans', sans-serif;
letter-spacing: 3px;
font-size: 11px;
text-transform: uppercase;
margin: 0;
width: 35%;
font-weight: 700;
text-decoration: none;
transform: translateY(25%);
opacity: 0;
visibility: hidden;
transition: 0.6s all ease-in-out;
}
.carousel__nav {
position: absolute;
right: 0;
z-index: 2;
background-color: #fff;
bottom: 0;
}
.carousel__icon {
display: inline-block;
vertical-align: middle;
width: 16px;
fill: #5d5d5d;
}
.carousel__arrow {
cursor: pointer;
display: inline-block;
padding: 11px 15px;
position: relative;
}
.carousel__arrow:nth-child(1):after {
content: '';
right: -3px;
position: absolute;
width: 1px;
background-color: #b0b0b0;
height: 14px;
top: 50%;
margin-top: -7px;
}
.active {
z-index: 1;
display: flex;
visibility: visible;
}
.active .carousel-item__subtitle, .active .carousel-item__title, .active .carousel-item__description, .active .carousel-item__btn {
transform: translateY(0);
opacity: 1;
transition: 0.6s all ease-in-out;
visibility: visible;
}
.active .carousel-item__image {
transition: 0.6s all ease-in-out;
transform: translateX(0);
}
.box {
width: 30px;
height: 60px;
display: table;
}
.wrap {
display: table-cell;
verical-align: middle;
}
3. 错误页面js
$(function () {
$('.carousel-item').eq(0).addClass('active');
var total = $('.carousel-item').length;
var current = 0;
$('#moveRight').on('click', function () {
var next = current;
current = current + 1;
setSlide(next, current);
});
$('#moveLeft').on('click', function () {
var prev = current;
current = current - 1;
setSlide(prev, current);
});
function setSlide(prev, next) {
var slide = current;
if (next > total - 1) {
slide = 0;
current = 0;
}
if (next < 0) {
slide = total - 1;
current = total - 1;
}
$('.carousel-item').eq(prev).removeClass('active');
$('.carousel-item').eq(slide).addClass('active');
setTimeout(function () {
}, 800);
console.log('current ' + current);
console.log('prev ' + prev);
}
});
4. 配置WebSecurityConfig
package com.example.springscuritydemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.mvcMatchers("/login.html").permitAll()
.mvcMatchers("/login.css").permitAll()
.mvcMatchers("/error.html").permitAll()
.mvcMatchers("/error.css").permitAll()
.mvcMatchers("/error.js").permitAll()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin()
//设置登录页面
.loginPage("/login.html")
.loginProcessingUrl("/login") // 设置验证请求路径
// .successForwardUrl("/test/hello") //验证成功后请求转发到指定页面 请求转发到指定页
//验证成功后默认跳转到第一次发送请求页面
// .defaultSuccessUrl("/index/hello") // 设置默认跳转页面 请求重定向到指定页
.usernameParameter("usern") //设置用户名属性
.passwordParameter("paswd") //设置密码属性
// .successHandler(new MyAuthenticationSuccessHandler())// 设置返回处理器
.failureUrl("/error.html")//请求失败后跳转页面 以redirect方法跳转
// .failureForwardUrl("/error.html") // 以 forward方式跳转
//禁用crsf
.and().csrf().disable();
}
}
2. 自定义异常处理
package com.example.springscuritydemo.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author 崔令雨
* @date 2022/5/21 19:47
* @Version 1.0
*/
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
Map map = new HashMap<>();
map.put("Message", exception.getMessage());
response.setContentType("application/json;charset=utf-8");
String s = new ObjectMapper().writeValueAsString(map);
response.getWriter().println(s);
}
}
配置security
package com.example.springscuritydemo.config;
import com.example.springscuritydemo.handler.MyAuthenticationFailureHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.mvcMatchers("/login.html").permitAll()
.mvcMatchers("/login.css").permitAll()
.mvcMatchers("/error.html").permitAll()
.mvcMatchers("/error.css").permitAll()
.mvcMatchers("/error.js").permitAll()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin()
//设置登录页面
.loginPage("/login.html")
.loginProcessingUrl("/login") // 设置验证请求路径
// .successForwardUrl("/test/hello") //验证成功后请求转发到指定页面 请求转发到指定页
//验证成功后默认跳转到第一次发送请求页面
// .defaultSuccessUrl("/index/hello") // 设置默认跳转页面 请求重定向到指定页
.usernameParameter("usern") //设置用户名属性
.passwordParameter("paswd") //设置密码属性
// .successHandler(new MyAuthenticationSuccessHandler())// 设置返回处理器
// .failureUrl("/error.html")//请求失败后跳转页面 以redirect方法跳转
// .failureForwardUrl("/error.html") // 以 forward方式跳转
.failureHandler(new MyAuthenticationFailureHandler())
//禁用crsf
.and().csrf().disable();
}
}
注销登录
- 注销之后跳转页面
package com.example.springscuritydemo.config;
import com.example.springscuritydemo.handler.MyAuthenticationFailureHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.mvcMatchers("/login.html").permitAll()
.mvcMatchers("/login.css").permitAll()
.mvcMatchers("/error.html").permitAll()
.mvcMatchers("/error.css").permitAll()
.mvcMatchers("/error.js").permitAll()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin()
//设置登录页面
.loginPage("/login.html")
.loginProcessingUrl("/login") // 设置验证请求路径
// .successForwardUrl("/test/hello") //验证成功后请求转发到指定页面 请求转发到指定页
//验证成功后默认跳转到第一次发送请求页面
// .defaultSuccessUrl("/index/hello") // 设置默认跳转页面 请求重定向到指定页
.usernameParameter("usern") //设置用户名属性
.passwordParameter("paswd") //设置密码属性
// .successHandler(new MyAuthenticationSuccessHandler())// 设置返回处理器
// .failureUrl("/error.html")//请求失败后跳转页面 以redirect方法跳转
// .failureForwardUrl("/error.html") // 以 forward方式跳转
.failureHandler(new MyAuthenticationFailureHandler())
//禁用crsf
.and()
.logout()//
// .logoutUrl("/logout")// 指定注销登录的请求路径默认get方式
.logoutRequestMatcher(
new AntPathRequestMatcher("/aa", "GET") //自定义退出路径以及请求方式
)
.and().csrf().disable();
}
}
-
注销之后返回json
配置注销处理器
package com.example.springscuritydemo.handler;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author 崔令雨
* @date 2022/5/22 9:44
* @Version 1.0
*/
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
Map map = new HashMap<>();
map.put("msg", authentication);
map.put("status", 200);
response.setContentType("application/json;charset=utf-8");
String s = new ObjectMapper().writeValueAsString(map);
response.getWriter().println(s);
}
}
修改security配置
package com.example.springscuritydemo.config;
import com.example.springscuritydemo.handler.MyAuthenticationFailureHandler;
import com.example.springscuritydemo.handler.MyLogoutSuccessHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
/**
* @author 崔令雨
* @date 2022/5/21 13:44
* @Version 1.0
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeHttpRequests()
.mvcMatchers("/login.html").permitAll()
.mvcMatchers("/login.css").permitAll()
.mvcMatchers("/error.html").permitAll()
.mvcMatchers("/error.css").permitAll()
.mvcMatchers("/error.js").permitAll()
//匹配请求路径 并放行 /index/hello 最左边的斜杠必须加 不然失效
.mvcMatchers("/index/hello").permitAll()
// 所有请求 认证后放行
.anyRequest().authenticated()
//认证方式表单认证
.and().formLogin()
//设置登录页面
.loginPage("/login.html")
.loginProcessingUrl("/login") // 设置验证请求路径
// .successForwardUrl("/test/hello") //验证成功后请求转发到指定页面 请求转发到指定页
//验证成功后默认跳转到第一次发送请求页面
// .defaultSuccessUrl("/index/hello") // 设置默认跳转页面 请求重定向到指定页
.usernameParameter("usern") //设置用户名属性
.passwordParameter("paswd") //设置密码属性
// .successHandler(new MyAuthenticationSuccessHandler())// 设置返回处理器
// .failureUrl("/error.html")//请求失败后跳转页面 以redirect方法跳转
// .failureForwardUrl("/error.html") // 以 forward方式跳转
.failureHandler(new MyAuthenticationFailureHandler())
//禁用crsf
.and()
.logout()//
// .logoutUrl("/logout")// 指定注销登录的请求路径默认get方式
.logoutRequestMatcher(
new AntPathRequestMatcher("/aa", "GET") //自定义退出路径以及请求方式
)
.logoutSuccessHandler(new MyLogoutSuccessHandler())
.and().csrf().disable();
}
}
获取用户数据
- 单线程获取用户数据
package com.example.springscuritydemo.controller;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 崔令雨
* @date 2022/5/21 13:42
* @Version 1.0
*/
@RestController
@RequestMapping("index")
public class IndexController {
@RequestMapping("hello")
public String hello() {
return "index hello";
}
@RequestMapping("user")
public String user() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
System.out.println("authentication.getPrincipal() = " + authentication.getPrincipal());
System.out.println("authentication.getAuthorities() = " + authentication.getAuthorities());
return "hello user";
}
}
- 多线程模式下获取用户数据
需要对vm options 参数修改 之后在运行过程中 主线程会将用户信息复制一份放到子线程中
-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
- 在页面获取用户信息
- 引入依赖
org.thymeleaf.extras
thymeleaf-extras-springsecurity5
3.0.4.RELEASE
在页面添加命名空间
获取用户信息