SpringBoot 学习笔记(十)Spring Security 安全框架_springboot之security学习

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

需要这份系统化资料的朋友,可以点击这里获取

public class UserController {
@RequestMapping(“/user/hello”)
public String hello() {
return “user,Hello !”;
}
}


AdminController类



package com.example.demo3springsecurity.controller;

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

@RestController
public class AdminController {
@RequestMapping(“/admin/hello”)
public String hello() {
return “admin,Hello !”;
}
}


2. 配置两个角色  
 本来用户和角色是保存在数据库中的,这里只是单纯地创建了两个存放于内存的用户和角色  
 创建config目录,并创建SecurityConfig类



package com.example.demo3springsecurity.config;

import org.springframework.context.annotation.Bean;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/*不对密码进行加密*/
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
/*管理员用户 具备ADMIN和USER角色*/
.withUser(“admin”).password(“admin”).roles(“ADMIN”, “USER”)
.and()
/*普通用户*/
.withUser(“aoxiu”).password(“aoxiu”).roles(“USER”);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
/*普通用户访问的url*/
.antMatchers(“/user/**”).hasRole(“USER”)
/*管理员用户访问的url*/
.antMatchers(“/admin/**”).hasRole(“ADMIN”)
.anyRequest().authenticated() //其他多有路径都必须认证
.and()
.formLogin()
.loginProcessingUrl(“/login”)
.permitAll() //访问“/login”接口不需要进行身份认证了,防止重定向死循环
.and()
.csrf().disable(); //关闭csrf
}
}


然后就可以发现,若要访问admin/hello,用户名和密码必须是admin才可以  
 若使用aoxiu这种用户的身份就会报错


### 三、基于数据库的认证


#### 1、SpringSecurity基于数据库认证


1. 创建项目,添加如下依赖  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/7ec50386b596485b949e2fe9de929df0.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aWl5aaZ5peg56m5,size_12,color_FFFFFF,t_70,g_se,x_16)  
 lombok用于使用注解替代getter、setter等方法  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/547e093d08cf4cb7a92173434b6cbafd.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aWl5aaZ5peg56m5,size_14,color_FFFFFF,t_70,g_se,x_16)
2. 在application.yml文件中配置



spring:
datasource:
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
logging:
level:
com.example.bdatabaserole.mapper: debug #打印SQL语句
mybatis:
mapper-locations: classpath:mappers/*.xml
type-aliases-package: com.example.securitydatebase.mapper
server:
port: 8082


3. 创建实体类  
 UserInfo



package com.beixi.entity;

import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

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

@Data //lombok注解省略get/set等方法
public class UserInfo implements Serializable,UserDetails {
private int id;

private String username;
private String password;
private List<Role> roleList;

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
    Collection<GrantedAuthority> authorities = new ArrayList<>();
    for (Role role : roleList) {
        //数据库role表字段中是以ROLE\_开头的,所以此处不必再加ROLE\_
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    }
    return authorities;
}

/\*\*

* 指示用户的账户是否已过期。无法验证过期的账户。
* 如果用户的账户有效(即未过期),则返回true,如果不在有效就返回false
*/
@Override
public boolean isAccountNonExpired() {
return true;
}

/\*\*

* 指示用户是锁定还是解锁。无法对锁定的用户进行身份验证。
* 如果用户未被锁定,则返回true,否则返回false
*/
@Override
public boolean isAccountNonLocked() {
return true;
}

/\*\*

* 指示用户的凭证(密码)是否已过期。过期的凭证阻止身份验证
* 如果用户的凭证有效(即未过期),则返回true
* 如果不在有效(即过期),则返回false
*/
@Override
public boolean isCredentialsNonExpired() {
return true;
}

/\*\*

* 指示用户是启用还是禁用。无法对禁用的用户进行身份验证
* 如果启用了用户,则返回true,否则返回false
*/
@Override
public boolean isEnabled() {
return true;
}
}


4. 创建Mapper接口和Service层  
 UserMapper



package com.example.securitydatebase.mapper;

import com.example.securitydatebase.entity.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {
@Select(“select * from user where username = #{username}”)
UserInfo getUserByUsername(String username);

}


UserInfoService



package com.example.securitydatebase.service;

import com.example.securitydatebase.entity.UserInfo;
import com.example.securitydatebase.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserInfoService {
@Autowired
private UserMapper userMapper;

public UserInfo getUserInfo(String username){
    return userMapper.getUserByUsername(username);
}

}


5. 创建Controller层



package com.example.securitydatebase.controller;

import com.example.securitydatebase.entity.UserInfo;
import com.example.securitydatebase.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class UserController {
@Autowired
private UserInfoService userInfoService;

@GetMapping("/getUser")
public UserInfo getUser(@RequestParam String username){
    return userInfoService.getUserInfo(username);
}

}


6. 身份认证  
 CustomUserDetailsService



package com.example.securitydatebase.service;

import com.example.securitydatebase.entity.UserInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

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

@Component
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserInfoService userInfoService;

/\*\*

* 需新建配置类注册一个指定的加密方式Bean,或在下一步Security配置类中注册指定
*/
@Autowired
private PasswordEncoder passwordEncoder;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    // 通过用户名从数据库获取用户信息
    UserInfo userInfo = userInfoService.getUserInfo(username);
    if (userInfo == null) {
        throw new UsernameNotFoundException("用户不存在");
    }
    //得到用户角色
    String role=userInfo.getRole();
    //角色集合
    List<GrantedAuthority> authorities=new ArrayList<>();
    //角色必须以“ROLE\_”开头,如果数据中没有,则在这里添加
    authorities.add(new SimpleGrantedAuthority("ROLE\_"+role));
    return new User(
        userInfo.getUsername(),
        //因为数据库是明文,所以这里需要加密密码
        passwordEncoder.encode(userInfo.getPassword()),
        authorities
    );
}

}


7. SpringSecurity配置  
 WebSecurityConfig



package com.example.securitydatebase.config;

import com.example.securitydatebase.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity //是Spring Security用于启用Web安全的注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Lazy
private CustomUserDetailsService userDatailService;

/\*\*

* 指定加密方式
*/
@Bean
public PasswordEncoder passwordEncoder(){
// 使用BCrypt加密密码
return new BCryptPasswordEncoder();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
        // 从数据库读取的用户进行身份认证
        .userDetailsService(userDatailService)
        .passwordEncoder(passwordEncoder());
}

}


8. 建立test数据库,建立user表  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/72fbd98785d24189af639ba7b5ff4955.png)
9. 测试  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/4e1aab3421ab4c049ef205bd53984c5e.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5aWl5aaZ5peg56m5,size_20,color_FFFFFF,t_70,g_se,x_16)  
 注意这一段只是用于认证,但是还没有限制角色的访问


#### 2、角色访问控制


1. 开启访问权限,在WebSecurityConfig中添加@EnableGlobalMethodSecurity  
 ![在这里插入图片描述](https://img-blog.csdnimg.cn/08c66b3797554aa1ae1e2513e47f7587.png)  
 prePostEnabled=true会解锁@PreAuthorize和@PostAuthorize两个注解,@preAuthorize注解会在方法执行前进行验证,而@PostAuthorize注解在方法执行后进行验证  
 是不是有点懵,没关系,看后面就懂了
2. 在控制层添加访问接口  
 UserController类增加方法的访问权限



@PreAuthorize("hasAnyRole('user')") // 只能user角色才能访问该方法
@GetMapping("/user")
public String user(){
    return "hello,user";
}

@PreAuthorize("hasAnyRole('admin')") // 只能admin角色才能访问该方法
@GetMapping("/admin")
public String admin(){
    return "hello,admin";
}

PreAuthorize在执行前会首先验证是否user角色


3. 测试


使用user登录时无法访问/admin,  
 使用admin界面时,无法访问/user


#### 3、密码加密保护


1. 修改Mapper接口



package com.example.securitydatebase.mapper;

import com.example.securitydatebase.entity.UserInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;

@Mapper
@Repository
public interface UserMapper {
@Select(“select * from user where username = #{username}”)
UserInfo getUserByUsername(String username);

// 添加用户
@Insert("insert into user(username, password) value(#{username}, #{password})")
int insertUserInfo(UserInfo userInfo);

}


2. 修改service类



package com.example.securitydatebase.service;

import com.example.securitydatebase.entity.UserInfo;
import com.example.securitydatebase.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserInfoService {
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
public int insertUser(UserInfo userInfo){
// 加密密码
userInfo.setPassword(passwordEncoder.encode(userInfo.getPassword()));
return userMapper.insertUserInfo(userInfo);
}

public UserInfo getUserInfo(String username){
    return userMapper.getUserByUsername(username);
}

}


3. 修改controller




### 给大家的福利


**零基础入门**


对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)

因篇幅有限,仅展示部分资料

**需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)**

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

个大的方向学习准没问题。


![](https://img-blog.csdnimg.cn/img_convert/95608e9062782d28f4f04f821405d99a.png)


同时每个成长路线对应的板块都有配套的视频提供:


![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a91b9e8100834e9291cfcf1695d8cd42.png#pic_center)

因篇幅有限,仅展示部分资料

**需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)**

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化资料的朋友,可以点击这里获取](https://bbs.csdn.net/topics/618540462)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 27
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值