SpringBoot整合Spring Security

新鲜速递:Spring Boot 3 项目快速集成 Spring Security 6的方法 本文讲述Spring Boot 3 快速集成Spring Security 6的方法,以往的旧文章大多无法无错完成集成,所以笔者经过研究,在这里发布快速集成方法,避免读者重蹈覆辙掉入各种坑里。 阅读详情

Spring Security是什么

官网介绍 https://spring.io/projects/spring-security

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.
Spring Security is a framework that focuses on providing bothauthentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。
Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring安全性的真正威力在于它可以很容易地扩展以满足定制需求

功能:认证(Authentication)和 授权(Authorization)

一、初探Spring Security

1、新建一个springboot项目

在这里插入图片描述
新建一个Controller类

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @RequestMapping("/hello")
    public String hello(){
        return "Hello World!";
    }
}

源码地址
GitHub https://github.com/KingJin-web/springboot
Gitee https://gitee.com/KingJin-web/springboot

2、引入Spring Security

  		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

3、直接启动springboot

在这里插入图片描述
启动的时候会在控制台显示随机生成的密码。
这时访问http://localhost:8080/hello会重定向到http://localhost:8080/login,这个页面是Spring Security默认的。
在这里插入图片描述

4、登录

使用默认用户和随机生成的密码登录
spring security 默认的用户名是user,spring security启动的时候会生成默认密码(在启动日志中可以看到)。

我们填入user 和 上图显示的9b0c45dc-4f7e-4b0c-ae1a-007dea7dbcc5,那么就会正常的访问/hello。
在这里插入图片描述

5、在yml 文件中设置自定义密码实现登录

在application.yml中定义用户名密码:

spring:
  security:
    user:
      name: admin
      password: aaaa

使用自定义用户名和密码登录,可以正常访问/hello。

6、 使用代码中指定的用户名、密码登录

新建SecurityConfig 配置类继承 WebSecurityConfigurerAdapter
使用configure(AuthenticationManagerBuilder) 添加认证。
使用configure(httpSecurity) 添加权限
在这里插入图片描述

package com.king.security.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin") // 添加用户admin
                .password("{noop}aaaa")  // 不设置密码加密
                .roles("ADMIN", "USER")// 添加角色为admin,user
                .and()
                .withUser("user") // 添加用户user
                .password("{noop}bbbb")
                .roles("USER")
                .and()
                .withUser("temp") // 添加用户temp
                .password("{noop}cccc")
                .roles(); // 没有角色
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/user/**").hasRole("USER") //添加/user/** 下的所有请求只能由user角色才能访问
                .antMatchers("/admin/**").hasRole("ADMIN") //添加/admin/** 下的所有请求只能由admin角色才能访问
                .anyRequest().authenticated() // 没有定义的请求,所有的角色都可以访问(temp也可以)。
                .and()
                .formLogin().and()
                .httpBasic();
    }


}

添加AdminController、UserController

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/admin")
public class AdminController {
    @RequestMapping("/hello")
    public String hello(){
        return "Hello Admin!";
    }
}
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/hello")
    public String hello(){
        return "Hello User!";
    }
}

通过上面的设置,访问http://localhost:8080/admin/hello只能由admin访问,http://localhost:8080/user/hello admin和user都可以访问,http://localhost:8080/hello 所有用户(包括temp)都可以访问。

这里就很简易的实现了 Spring Security 的认证和授权功能,下面介绍如何结合数据库来实现

二、使用数据库的用户名、密码登录

这里数据库持久层使用spring data jpa 有兴趣的可以看看 SpringBoot整合Spring Data JPA访问MySQL

1、添加依赖

  		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

2、配置Spring Security认证和授权

SecurityConfig.java

先改一下配置类

import com.king.security.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @program: springboot
 * @description:
 * @author: King
 * @create: 2022-03-02 11:53
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter  {

    @Autowired
    private UserServiceImpl userService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService)// 设置自定义的userDetailsService
                .passwordEncoder(passwordEncoder());
    }

    private PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();// 使用不使用加密算法密码
    }



    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasAnyRole("USER","ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .httpBasic()
                .and()
                .logout().logoutUrl("/logout"); //退出登录
    }

}

User.java

定义一个实体类 建表语句就省略了 因为jpa会自动建表

import lombok.Builder;
import lombok.Data;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import javax.persistence.*;
import javax.persistence.criteria.Root;

@Entity
@Builder
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;//主键自增
    private String name;
    //密码
    private String password;
    //角色枚举 这个注解表示使用枚举类中的int
    @Enumerated(EnumType.ORDINAL)
    private Role role;

    public User() {

    }

    //@builder默认用的是全参数构造函数  没有这个会报错 也可以加@AllArgsConstructor
    public User(Long id, String name, String password, Role role) {
        this.id = id;
        this.name = name;
        this.password = password;
        this.role = role;
    }
}

Role.java

public enum Role {
    //这里为啥要加 ROLE_ ?
    ADMIN(1, "ROLE_ADMIN"),
    USER(2, "ROLE_USER"),
    TEMP(3, "ROLE_TEMP");


    private final Integer status;
    private final String text;

    Role(Integer status, String text) {
        this.status = status;
        this.text = text;
    }


    public Integer getStatus() {
        return status;
    }

    public String getText() {
        return text;
    }
}

这里为啥要加 ROLE_ ? 我们可以看看 SecurityConfig 中 hashRole 的源码
在这里插入图片描述
可见我们配置文件中设置角色都会自动加上 ROLE_ 前缀 然后如果你数据库里面的角色是ADMIN,网页里面写的也是admin, 在这个就会用admin和ROLE_admin 匹配, 然后就不行 所以需要加

UserMapper.java

这里使用的jpa 的方法名查询 就是根据用户名查一个用户出来 感兴趣可以看之前的文章
SpringBoot整合Spring Data JPA–进阶

import com.king.security.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserMapper  extends JpaRepository<User, Integer> {
    User findOneByName(String name);
}

UserServiceImpl.java

import com.king.security.entity.Role;
import com.king.security.entity.User;
import com.king.security.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;


@Service
public class UserServiceImpl implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;
    private final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
    private Example<User> em;

    /**
     * 注册用户
     *
     * @param name
     * @param pwd
     * @return
     */
    public User register(String name, String pwd, Role role) {
        if (isUserName(name)) {
            System.out.println("此昵称已经被占用");
            return null;
        }
        return userMapper.save(User.builder().name(name).password(pwd).role(role).build());
    }

    /**
     * 注册 密码为加密后的
     *
     * @param name
     * @param pwd
     * @return
     */
    public User registerByEncode(String name, String pwd, Role role) {
     	if (isUserName(name)) {
            System.out.println("此昵称已经被占用");
            return null;
        }
        pwd = encoder.encode(pwd);
        return userMapper.save(User.builder().name(name).password(pwd).role(role).build());
    }

    /**
     * 判断用户名是否被使用
     *
     * @param name
     * @return
     */
    public boolean isUserName(String name) {

        em = Example.of(User.builder().name(name).build());
        return userMapper.findAll(em).size() >= 1;
    }

    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
        User user = userMapper.findOneByName(name);
        if (user == null){
            throw new UsernameNotFoundException("此用户不存在");

        }
        
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(user.getRole().getText());
        grantedAuthorities.add(grantedAuthority);

        return new org.springframework.security.core.userdetails.User(name,
                user.getPassword(), grantedAuthorities);
    }


}

3、添加用户

import com.king.security.entity.Role;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class UserServiceImplTest {

    @Autowired
    private UserServiceImpl userService;

    @Test
    public void register() {
        userService.register("admin","aaaa", Role.ADMIN);
        userService.register("user","aaaa", Role.USER);
        userService.register("king","aaaa", Role.TEMP);
    }

	//生成三个密码加密了的用户名
    @Test
    public void registerByEncode() {
        userService.registerByEncode("admin1","aaaa", Role.ADMIN);
        userService.registerByEncode("user1","aaaa", Role.USER);
        userService.registerByEncode("king1","aaaa", Role.TEMP);
    }

}

在这里插入图片描述

4、获取登录信息

我们在上文的 HelloController 加入这个方法 来在浏览器获取登录信息
使用SecurityContextHolder.getContext().getAuthentication().getPrincipal();获取当前的登录信息。

    /**
     * 获得用户登录信息
     * @return
     */
    @RequestMapping("/info")
    public Object info(){
        return SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    }

登录后就可通过 http://localhost:8080/info 来获取登录信息
在这里插入图片描述

这里通过数据库来实现用户名和密码登录就基本完成了

5、Spring Security 密码加密

只需要修改 配置类 SecurityConfig.java 中的 passwordEncoder 方法即可
当然登录的账号数据库存储的密码也需要是加密后的

    private PasswordEncoder passwordEncoder() {
        //return NoOpPasswordEncoder.getInstance();// 使用不使用加密算法保持密码
        return new BCryptPasswordEncoder();
    }

最后附上我的演示例源码

Github https://github.com/KingJin-web/springboot

Gitee https://gitee.com/KingJin-web/springboot
以上内容属于个人笔记整理,如有错误,欢迎批评指正!

Springboot3 + SpringSecurity + JWT + OpenApi3 实现认证授权 目前全网最新的 Spring Security + JWT 实现双 Token 的案例!此项目由作者个人创作,可以供大家学习和项目实战使用,创作不易,转载请注明出处!该项目使用目前最新的 Sprin Boot3 版本,采用目前市面上最主流的 JWT 认证方式,实现双token刷新。温馨提示:SpringBoot3 版本必须要使用 JDK11 或 JDK19。 阅读详情

相关推荐

springboot3整合SpringSecurity实现登录校验与权限认证(万字超详细讲解)

用户提交登录请求Spring Security 将请求交给 UsernamePasswordAuthenticationFilter 过滤器处理。UsernamePasswordAuthenticationFilter 获取请求中的用户名和密码,并生成一个 AuthenticationToken 对象,将其交给 AuthenticationManager 进行认证。

web15085096641的博客 1113

SpringBoot3.0 + SpringSecurity6.0+JWT

SpringBoot3.0 + SpringSecurity6.0+JWTSpring Security 是 Spring 家族中的一个安全管理框架。一般Web应用的需要进行认证和授权。认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户授权:经过认证后判断当前用户是否有权限进行某个操作搭建一个SpringBoot工程① 设置父工程 添加依赖 配置文件application.yml ② 创建启动类 ③ 创建Controller 启动项目,查看接口文档地址:http://localhost:4

胖胖爱吃肉~的博客 2万+

springboot + spring security + swagger 整合

springboot整合 spring security 和swagger-ui : pom.xml文件中添加相关依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> .

不要总是等明天再开始 9436

Spring Boot 整合 Spring Security

Spring Boot 整合 Spring Security

hutao8896的博客 1240

SpringBoot整合Spring Security【超详细教程】

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。提供了完善的认证机制和方法级的授权功能。是一款非常优秀的权限管理框架。它的核心是一组过滤器链,不同的功能经由不同的过滤器。这篇文章就是想通过一个小案例将Spring Security整合到SpringBoot中去。要实现的功能就是在认证服务器上登录,然后获取Token,再访问资源服务器中的资源。什么叫做单点登录呢。就是在一个多应用系统中,只要在其中一个系统上登录之后,不需要在其它系统上登录也可以访问其内容。举个例子,京东那么复

m0_52789121的博客 8884

springboot 重定向html_Spring Boot整合Spring Security

本示例基于spring boot1.5.9.RELEASE在Spring boot项目中使用 SpringSecurity实现权限管理很简单,只需要引入依赖,然后编写授权和认证的相关自定义规则即可。创建一个web的Spring Boot项目来整合Spring Security,并以此为基础进行讲解。下面具体演示一下。(1)相关依赖<dependency> <gro...

weixin_39890652的博客 508

Spring Boot整合Spring Security

在我们深入研究整合过程之前,让我们先来了解一下Spring Security。是基于Spring框架的安全性解决方案,它提供了全面的安全性服务,包括身份验证(Authentication)、授权(Authorization)、攻击防护等。通过使用Spring Security,我们可以轻松地在我们的应用程序中实现各种安全功能,确保用户数据的保密性和完整性。通过以上简单的步骤,我们成功地将Spring Boot与Spring Security整合在一起,为我们的应用程序提供了强大的安全保障。

微赚淘客开发者博客 592

Spring Boot:整合Spring Security

综合概述 Spring Security 是 Spring 社区的一个顶级项目,也是 Spring Boot 官方推荐使用的安全框架。除了常规的认证(Authentication)和授权(Authorization)之外,Spring Security还提供了诸如ACLs,LDAP,JAAS,CAS等高级特性以满足复杂场景下的安全需求。另外,就目前而言,Spring Security和Shiro也是当前广大应用使用比较广泛的两个安全框架。 Spring Security 应用级别的安全主要包含两个主要部

m0_68850571的博客 646

【Spring Security权限框架】SpringBoot整合Spring Security实现权限控制

SpringSecurity框架【详解】

weixin_45618869的博客 7076

【CANoe16安装教程】亲测安装成功

CANoe16安装教程

qq_45302638的博客 2万+

富士SC2022,C325,C328打印机扫描到网络详细教程

富士打印机SC2022,C328,C325等型号扫描到电脑教程

weixin_41926602的博客 1万+

Springboot整合Spring-security

Springboot整合spring-security 1.创建springboot项目 2.引入相关依赖。 spring-boot-starter-security mysql-connector-java persistence-api(mybaits注解支持) spring-security-core spring-boot-starter-thymeleaf //springboot对thymeleaf的支持 thymeleaf-spring5 thymeleaf-extras-ja

weixin_43423541的博客 253

别再到处找模型了!手把手教你用Xinference+Docker部署本地私有大模型(Llama2/Qwen实战)

本文详细介绍了如何使用Xinference和Docker部署本地私有化大模型(如Llama2/Qwen),涵盖硬件配置、模型管理、Docker部署及性能优化等关键步骤。通过实战案例,帮助开发者快速构建企业级AI推理服务,确保数据安全与高效运行。

weixin_28683065的博客 231

Spring Boot整合WebSocket及Spring Security实例

一.为什么需要WebSocket在HTTP协议中,所有请求都是由客户端发起的,由服务端进行响应,服务端无法向客户推送消息,但是在一些需要即时通信的应用中,有不可避免的需要服务端向客户端推送消息,传统的解决方案有如下几种1.轮询轮询是最简单的解决方案,其意义在于,客户端在固定的时间间隔下不停地向服务端发送请求,查看服务端是否有新的数据,若服务端有新的数据,则返回给客户端,若是服务端没有新的数据,则返...

weixin_34174322的博客 6517

手把手拆解DGX GB200 NVL72:1个机柜如何塞进72块GPU?详解NVLink Switch铜缆背板设计

本文深度解析英伟达DGX GB200 NVL72系统如何通过NVLink Switch铜缆背板设计,在标准42U机柜中集成72块B200 GPU,实现1800GB/s的超高带宽。文章详细介绍了模块化架构、铜缆互连技术、液冷散热方案和高密度供电系统等核心创新,为AI算力需求提供突破性解决方案。

red88的博客 1563

从CCD数据上报看wxHOOK的封号风险与规避

本文深入分析了微信CCD数据上报机制对wxHOOK的检测逻辑与封号风险,揭示了调试器路径暴露、非白名单DLL加载和内存校验失败等关键风险点。通过实战案例和规避方案,帮助开发者理解如何安全使用wxHOOK技术,避免封号风险,包括内存镜像欺骗、内核级隐蔽和硬件辅助方案等高级技巧。

weixin_27875131的博客 625

Spring Boot与Spring Security的整合指南

Spring Boot与Spring Security的整合指南 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! Spring Boot是一个快速开发的Spring框架,而Spring Security是Spring提供的一个功能强大且高可定制的安全管理框架。将Spring Securi...

weixin_34665386的博客 192

【深度学习新浪潮】算力行业的核心技术有哪些?

算力行业核心技术是芯片+互联+存储+调度+能效+软件的全栈协同:芯片提供算力、互联打通集群、存储保障数据、调度提升效率、能效支撑规模、软件释放算力。当前AI大模型推动算力从“单机”走向“万卡级超节点集群”,技术竞争从单一芯片升级为系统级、全栈化的综合能力。

专注:太空算力、AI infra、异构调度、大模型成本工程 334
上一篇: 青龙常见问题整理,其他可用仓库以及通知设置
下一篇: Docker 入门 - Docker安装,镜像加速
盛夏省下
博客等级 码龄8年 6012粉丝 100原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值