1.创建springBoot 项目工程(spring6.0的底层、JDK17)

1.添加依赖
<dependency>
            &lt;groupId&gt;org.springframework.boot</groupId&gt;
            <artifactId&gt;spring-boot-starter-security</artifactId&gt;
        </dependency&gt;

配置完成启动访问controller出现登录页面
在这里插入图片描述

默认用户user 密码 控制台uuid输出,跟踪源码可以看到
在这里插入图片描述

2 使用配置用户名密码
  security:
    user:
      name: admin
      password: 123456

使用自己配置的登录然后可以访问控制api

3.退出登录

http://127.0.0.1:8080/logout
在这里插入图片描述

2.基于内存多用户管理

在这里插入图片描述

1.创建用户详情接口配置


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

//自定义配置实现用户详情
@Configuration
public class MyUserSecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user1 = User.builder().username("admin").password("123456").build();
        UserDetails user2 = User.builder().username("test").password("123456").build();
        InMemoryUserDetailsManager memoryUserDetailsManager = new InMemoryUserDetailsManager();
        memoryUserDetailsManager.createUser(user1);
        memoryUserDetailsManager.createUser(user2);

        return memoryUserDetailsManager;
    }


}

访问接口登录 test test 报错如下
在这里插入图片描述
必须加密
修改配置

package com.example.db.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

//自定义实现用户详情接口
@Configuration
public class MyUserSecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user1 = User.builder().username("admin").password("123456")
                .roles("admin").build();
        UserDetails user2 = User.builder().username("test").password("123456")
                .roles("stu").build();
        InMemoryUserDetailsManager memoryUserDetailsManager = new InMemoryUserDetailsManager();
        memoryUserDetailsManager.createUser(user1);
        memoryUserDetailsManager.createUser(user2);

        return memoryUserDetailsManager;
    }

    //配置密码加密器
    //没有加密NoOpPasswordEncoder
    @Bean
    public PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }


}

通过上面配置可以正常登录,访问api接口配置文件中的用户失效

3.密码加密

1.CSDN密码泄露事件数据库明文存储
1.前端密码加密给后端使用相同密码加密规则前端加密对比数据库密码校验规则

常见加密算法MD5 sha RSA

2、使用PasswordEncoder接口提供的实现

加盐干扰因子
BCryptPasswordEncoder 加密和校验原始密码

BCryptPasswordEncoder cryptPasswordEncoder=new BCryptPasswordEncoder();
        String encode = cryptPasswordEncoder.encode("123456");

        String encode2 = cryptPasswordEncoder.encode("123456");
        String encode3 = cryptPasswordEncoder.encode("123456");
        log.info(encode);
        log.info(encode2);
        log.info(encode3);
        boolean pwd1 = cryptPasswordEncoder.matches("123456", encode);
        boolean pwd2 = cryptPasswordEncoder.matches("123456", encode2);
        boolean pwd3 = cryptPasswordEncoder.matches("123456", encode3);
        log.info("pwd1="+pwd1);
        log.info("pwd2="+pwd2);
        log.info("pwd3="+pwd3);

在这里插入图片描述
加密上面文明密码


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

//自定义实现用户详情接口
@Configuration
public class MyUserSecurityConfig {

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails user1 = User.builder().username("admin").password(passwordEncoder().encode("123456"))
                .roles("admin").build();
        UserDetails user2 = User.builder().username("test").password(passwordEncoder().encode("654321"))
                .roles("stu").build();
        InMemoryUserDetailsManager memoryUserDetailsManager = new InMemoryUserDetailsManager();
        memoryUserDetailsManager.createUser(user1);
        memoryUserDetailsManager.createUser(user2);

        return memoryUserDetailsManager;
    }

    //配置密码加密器
    //没有加密NoOpPasswordEncoder
    @Bean
    public PasswordEncoder passwordEncoder() {
//        return NoOpPasswordEncoder.getInstance();
        return new BCryptPasswordEncoder();

    }


}

在这里插入代码

返回登录信息测试
添加控制器

package com.example.db.control;

import org.springframework.boot.autoconfigure.neo4j.Neo4jProperties;
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;

import java.security.Principal;

@RestController
@RequestMapping("/user")
public class UserController {

    @GetMapping("/loginUser")
    public Authentication loginUser(Authentication authentication) {
        return authentication;
    }

    @GetMapping("/loginUser2")
    public Principal loginUser2(Principal principal) {
        return principal;
    }

    @GetMapping("/loginUser3")
    public Principal loginUser3() {
        //通过安全上下文持有器
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication;
    }
}

访问接口返回登录用户的信息如下
在这里插入图片描述
配置权限

UserDetails user1 = User.builder().username("admin").password(passwordEncoder().encode("123456"))
                .roles("admin")
                .authorities("stu:del") //配置权限
{
	"authorities": [{
		"authority": "stu:del"
	}],
	"details": {
		"remoteAddress": "127.0.0.1",
		"sessionId": "026ED34E46FC9022C29B200090F14924"
	},
	"authenticated": true,
	"principal": {
		"password": null,
		"username": "admin",
		"authorities": [{
			"authority": "stu:del"
		}],
		"accountNonExpired": true,
		"accountNonLocked": true,
		"credentialsNonExpired": true,
		"enabled": true
	},
	"credentials": null,
	"name": "admin"
}
4.基于方法授权

开启@EnableGlobalMethodSecurity(prePostEnabled = true)

package com.example.db.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

//从 Spring Security 5.7.0-M2开始 WebSecurityConfigurerAdapter 被标记过期,鼓励用户转向基于组件的 security 配置
@Configuration
@Slf4j
//全局方法授权

@EnableWebSecurity  // 启用SpringSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
                .anyRequest().authenticated());

        http.formLogin().permitAll();
        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/test/**");
    }


}


控制器配置

package com.example.db.control;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/student")
@RestController
public class StudentController {

    @GetMapping("/stu")
    @PreAuthorize("hasAuthority('stu')")
    public String test() {
        return "I am a student";
    }
}

5.处理结果返回JSON 前端处理

响应报文VO

package com.example.db.pojo;

import lombok.Data;

/**
 * 自定义响应结构
 */
@Data
public class Result {

    // 响应业务状态
    private Integer code;

    // 响应消息
    private String message;

    // 响应中的数据
    private Object data;

    public Result() {
    }

    public Result(Object data) {
        this.code = 200;
        this.message = "OK";
        this.data = data;
    }

    public Result(String message, Object data) {
        this.code = 200;
        this.message = message;
        this.data = data;
    }

    public Result(Integer code, String message, Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static Result ok() {
        return new Result(null);
    }

    public static Result ok(String message) {
        return new Result(message, null);
    }

    public static Result ok(Object data) {
        return new Result(data);
    }

    public static Result ok(String message, Object data) {
        return new Result(message, data);
    }

    public static Result build(Integer code, String message) {
        return new Result(code, message, null);
    }

    public static Result build(Integer code, String message, Object data) {
        return new Result(code, message, data);
    }


}

1.认证成功处理
package com.example.db.config;

import com.example.db.pojo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

//认证成功处理器
@Component
@Slf4j
public class AuthorSuccesssHandler implements AuthenticationSuccessHandler {


    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Result result=Result.build(1,"登录成功");

        String responsejson=objectMapper.writeValueAsString(result);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(responsejson);
        response.getWriter().flush();



    }
}

在这里插入图片描述

2.认证失败处理器
package com.example.db.config;

import com.example.db.pojo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
//认证失败处理器
@Component

public class AuthorFailHandler implements AuthenticationFailureHandler {

    @Autowired
   private ObjectMapper objectMapper;
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        Result result=Result.build(-1,"登陆失败");

        String responsejson=objectMapper.writeValueAsString(result);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(responsejson);
        response.getWriter().flush();
    }
}

在这里插入图片描述

3.退出登录处理器
package com.example.db.config;

import com.example.db.pojo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

//注销处理器
@Component
@Slf4j
public class AppLoginOutHandler implements LogoutSuccessHandler {
    @Autowired
    private ObjectMapper objectMapper;


    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Result result = Result.build(1, "退出登录成功");

        String responsejson = objectMapper.writeValueAsString(result);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(responsejson);
        response.getWriter().flush();
    }
}

在这里插入图片描述

4.资源访问拒绝处理
package com.example.db.config;

import com.example.db.pojo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

//资源访问拒绝处理
@Slf4j
@Component
public class AppAcessDeiedHandler implements AccessDeniedHandler {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        Result result = Result.build(0, "你没有权限访问资源");

        String responsejson = objectMapper.writeValueAsString(result);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(responsejson);
        response.getWriter().flush();
    }
}

在这里插入图片描述

5.配置各种处理
package com.example.db.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.web.SecurityFilterChain;

//从 Spring Security 5.7.0-M2开始 WebSecurityConfigurerAdapter 被标记为过期,鼓励用户转向基于组件的 security 配置
@Configuration
@Slf4j
//全局方法授权

@EnableWebSecurity  // 启用SpringSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

    //认证成功处理器
    @Autowired
    private AuthorSuccesssHandler authorSuccesssHandler;
    @Autowired
    //认证失败处理器
    private AuthorFailHandler authorFailHandler;

    //退出登录处理器

    @Autowired
    private AppLoginOutHandler appLoginOutHandler;

    //访问拒绝处理器
    @Autowired
    private AppAcessDeiedHandler appAcessDeiedHandler;


    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {


        http.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
                .anyRequest().authenticated());

        http.formLogin()
                .successHandler(authorSuccesssHandler)//认证成功
                .failureHandler(authorFailHandler)//认证失败


                .permitAll();

        http.logout().logoutSuccessHandler(appLoginOutHandler); //退出登录
        http.exceptionHandling().accessDeniedHandler(appAcessDeiedHandler);//访问资源失败

        return http.build();
    }

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/test/**");
    }


}


原文地址:https://blog.csdn.net/qq_30519365/article/details/134753702

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_43788.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注