security学习笔记

spring security 入门案例

  1. 创建springboot工程
  2. 引入依赖
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

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";
    }

}

  1. 启动程序访问我们的控制器方法 会弹出下图界面 用户名是 user 密码在控制台输出

image.png
image.png

修改默认用户名密码

  1. 在配置文件中配置用户名密码用来覆盖默认配置
spring.security.user.name=root
spring.security.user.password=root

image.png

自定义认证资源规则

  1. 自定义配置类继承 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();
    }
}

自定义登录页面

  1. 引入pom依赖
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
  1. 创建登录页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="login-box">
    <h2>Login</h2>
    <form method="post" th:action="/login">
        <div class="user-box">
            <input name="username" required="" type="text">
            <label>Username</label>
        </div>
        <div class="user-box">
            <input name="password" required="" type="password">
            <label>Password</label>
        </div>
        <a href="#">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            Submit
        </a>
    </form>
</div>
</body>
</html>

页面所需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%;
    }
}

  1. 关闭thymeleaf缓存
spring.thymeleaf.cache=false
  1. 定义控制器
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";
    }

}

  1. 设置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. 创建错误页面
<head>
  <title>FlexBox Exercise #3 - Image carousel / Responsive </title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
</head>

<body>
<div class="carousel">
  <div class="carousel__nav">
   <span id="moveLeft" class="carousel__arrow">
        <svg class="carousel__icon" width="24" height="24" viewBox="0 0 24 24">
    <path d="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"></path>
</svg>
    </span>
    <span id="moveRight" class="carousel__arrow" >
      <svg class="carousel__icon"  width="24" height="24" viewBox="0 0 24 24">
  <path d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"></path>
</svg>    
    </span>
  </div>
  <div class="carousel-item carousel-item--1">
    <div class="carousel-item__image"></div>
    <div class="carousel-item__info">
      <div class="carousel-item__container">
      <h2 class="carousel-item__subtitle">The grand moment </h2>
      <h1 class="carousel-item__title">Le tour</h1>
      <p class="carousel-item__description">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
      <a href="#" class="carousel-item__btn">Explore the tour</a>
        </div>
    </div>
  </div>
  <div class="carousel-item carousel-item--2">
    <div class="carousel-item__image"></div>
    <div class="carousel-item__info">
      <div class="carousel-item__container">
      <h2 class="carousel-item__subtitle">The big window </h2>
      <h1 class="carousel-item__title">Minimal window</h1>
      <p class="carousel-item__description">Clear Glass Window With Brown and White Wooden Frame iste natus error sit voluptatem accusantium doloremque laudantium.</p>
      <a href="#" class="carousel-item__btn">Read the article</a>
        </div>
    </div>
  </div>
    <div class="carousel-item carousel-item--3">
    <div class="carousel-item__image"></div>
    <div class="carousel-item__info">
      <div class="carousel-item__container">
      <h2 class="carousel-item__subtitle">Tropical palms </h2>
      <h1 class="carousel-item__title">Palms</h1>
      <p class="carousel-item__description">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
      <a href="#" class="carousel-item__btn">Explore the palms</a>
        </div>
    </div>
  </div>
  
   <div class="carousel-item carousel-item--4">
    <div class="carousel-item__image"></div>
    <div class="carousel-item__info">
      <div class="carousel-item__container">
      <h2 class="carousel-item__subtitle">Beach </h2>
      <h1 class="carousel-item__title">The beach </h1>
      <p class="carousel-item__description">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
      <a href="#" class="carousel-item__btn">Explore the beach</a>
        </div>
    </div>
  </div>
  
 <div class="carousel-item carousel-item--5">
    <div class="carousel-item__image"></div>
    <div class="carousel-item__info">
      <div class="carousel-item__container">
      <h2 class="carousel-item__subtitle">The white building </h2>
      <h1 class="carousel-item__title">White building</h1>
      <p class="carousel-item__description">Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam.</p>
      <a href="#" class="carousel-item__btn">Read the article</a>
        </div>
    </div>
  </div>
  
</div>
</body>
  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<String, Object> 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();
    }
}

注销登录

  1. 注销之后跳转页面
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();
    }
}

  1. 注销之后返回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<String, Object> 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();
    }
}

获取用户数据

  1. 单线程获取用户数据
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";
    }

}

  1. 多线程模式下获取用户数据

需要对vm options 参数修改 之后在运行过程中 主线程会将用户信息复制一份放到子线程中

-Dspring.security.strategy=MODE_INHERITABLETHREADLOCAL
  1. 在页面获取用户信息
    1. 引入依赖
<dependency>
  <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-springsecurity5</artifactId>
  <version>3.0.4.RELEASE</version>
</dependency>

在页面添加命名空间

<html lang="en" xmlns:th="https://www.thymeleaf.org" 
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
获取用户信息
<!--获取认证用户名-->
<ul>
  <li sec:authentication="principal.username"></li>
  <li sec:authentication="principal.authorities"></li>
  <li sec:authentication="principal.accountNonExpired"></li>
  <li sec:authentication="principal.accountNonLocked"></li>
  <li sec:authentication="principal.credentialsNonExpired"></li>
</ul>
posted @ 2022-05-22 15:44  01cui  阅读(55)  评论(0编辑  收藏  举报