SpringSecurity安全框架

我们使用这个springSecurity安全框架,作用是认证,授权,将用户的权限和对应的资源进行绑定,默认的是在内存中保存的,实际开发中,是需要根据项目业务的需求对某些方法进行重写,使数据库中权限对应的资源进行绑定,就是查看当前登录的用户所扮演的角色,该角色有哪些权限

授权

1内存交互资源绑定

这是框架默认的绑定方式,根据业务需求可以重写某些方法,连接数据库,进行交互进行资源绑定

复制代码
inMemoryAuthentication

1创建一个SpringBoot项目

2配置类MySecurityConfig

java 复制代码
package com.aaa.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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    //加密
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();//新建密码加密器
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //内存交互
        auth.inMemoryAuthentication()
                .withUser("zhangsan")
                .password(passwordEncoder().encode("123456"))
                .roles("admin")
                .authorities("user:query", "user:delete", "user:update", "user:insert")//手动设置的用户权限绑定资源,有4个权限
                .and()
                .withUser("lisi")
                .password(passwordEncoder().encode("123456"))
                .roles("test")
                .authorities("user:query", "user:export")//有两个权限
        ;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //登录前
        http.formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/mylogin")
                .successForwardUrl("/success")

                .failureUrl("/fail.html") // 直接指向一个HTML页面
                .permitAll();
        //登录后
        http.exceptionHandling().accessDeniedPage("/403.html");
        //禁止2跨域伪造请求的验证
        http.csrf().disable();
        http.authorizeRequests().anyRequest().authenticated();
    }
}

3添加注解

java 复制代码
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启安全框架注解

4在controller层加注解

在对应的方法上加注解

java 复制代码
@PreAuthorize(value="hasAnyAuthority('user:query')")
java 复制代码
package com.aaa.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyUserController {
    @GetMapping("query")
    @PreAuthorize(value="hasAnyAuthority('user:query')")
    public String query(){
        System.out.println("访问查询资源");
        return "查询资源";
    }
    @GetMapping("delete")
    @PreAuthorize(value = "hasAuthority('user:delete')")
    public String delete(){
        System.out.println("访问删除资源");
        return "删除资源";
    }
    @GetMapping("update")
    @PreAuthorize(value = "hasAuthority('user:update')")
    public String update(){
        System.out.println("访问修改资源");
        return "修改资源";
    }
    @GetMapping("insert")
    @PreAuthorize(value = "hasAuthority('user:insert')")
    public String insert(){
        System.out.println("访问添加资源");
        return "添加资源";
    }
    @GetMapping("export")
    @PreAuthorize(value = "hasAuthority('user:export')")
    public String export(){
        System.out.println("访问导出资源");
        return "导出资源";
    }
}

2与数据库交互进行权限的资源绑定

1添加依赖

java 复制代码
<!--添加依赖-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

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

    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.33</version>
    </dependency>

    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.26</version>
    </dependency>

2写属性文件

加载资源文件

3创建dao层和entity(实体类)

举一个接口和一个实体类例子

user-role-permission,

从用户表到角色表,再到权限表

sys_user--->sys_user_role--->sys_role_permission--->sys_permission

mybatis-plus先根据条件(用户的名)从用户表sys_user筛选,获取用户id,

然后拿着用户的id从用户角色表sys_user_role获取到用户所对应的roleid,

接着拿着roleid从角色权限表sys_role_permission获取permissionid,

再拿着权限id,(permissionid)到权限表sys_permission里获取所有全部权限信息,

最后绑定到用户上

sql语句

sql 复制代码
select DISTINCT sys_permission.* from sys_permission
join sys_role_permission 
on sys_permission.perid=sys_role_permission.perid
join sys_user_role 
on sys_role_permission.roleid=sys_user_role.roleid
where sys_user_role.userid=#{userid}

4 写自己的业务层

根据业务需求,重写框架的某些默认方法,进行权限绑定

java 复制代码
package com.aaa.service;

import com.aaa.dao.PermissionDao;
import com.aaa.dao.UserDao;
import com.aaa.entity.Permission;
import com.aaa.entity.User;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;

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.stereotype.Service;

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

@Service
public class MyUserDetailService implements UserDetailsService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private PermissionDao permissionDao;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //完成根据账户查询数据库即可
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",username);
        User user = userDao.selectOne(queryWrapper);
        if(user!=null){
            //permissions集合,源类型的集合,源集合--->目标类型的集合转换
            List<Permission> permissions = permissionDao.selectByUserId(user.getUserid());
            //空的SimpleGrantedAuthority类型的数组,目标类型的集合
            Collection<SimpleGrantedAuthority> authorities= new ArrayList<>();
            for (Permission per:permissions) {
                //把permissions集合里的东西拿出来,放到空集合里
                SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(per.getPercode());
                authorities.add(simpleGrantedAuthority);
            }
            org.springframework.security.core.userdetails.User userDetail =
                    new org.springframework.security.core.userdetails.User(user.getUsername(),user.getUserpwd(),authorities);
            return userDetail;

        }
        return null;
    }

}

5再配置类MySecurityConfig

用自己写的业务替换掉框架给的

java 复制代码
package com.aaa.config;
import com.aaa.service.MyUserDetailService;
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.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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailService myUserDetailService;
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //数据库交互

      
        auth.userDetailsService(myUserDetailService);
        //内存交互
//        auth.inMemoryAuthentication()
//                .withUser("zhangsan")
//                .password(passwordEncoder().encode("123456"))
//                .roles("admin")
//                .authorities("user:query","user:delete","user:update","user:insert")
//                .and()
//                .withUser("lisi")
//                .password(passwordEncoder().encode("123456"))
//                .roles("test")
//                .authorities("user:query","user:export")//

        ;

    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/mylogin")
                .successForwardUrl("/success")

                .failureUrl("/fail.html") // 直接指向一个HTML页面
                .permitAll();
//        http.authorizeRequests()
//                .antMatchers("/query").hasAnyAuthority("user:query")
//                .antMatchers("/delete").hasAnyAuthority("user:delete")
//                .antMatchers("/update").hasAnyAuthority("user:update")
//                .antMatchers("/insert").hasAnyAuthority("user:insert")
//                .antMatchers("/export").hasAnyAuthority("user:export");
        http.exceptionHandling().accessDeniedPage("/403.html");
        //禁止2跨域伪造请求的验证
        http.csrf().disable();
        http.authorizeRequests().anyRequest().authenticated();
    }
}

总结

根据业务需求调用自己的业务层(自己写的),去代替框架的部门业务实现需求

相关推荐
欢乐少年19043 小时前
SpringBoot集成Sentry日志收集-3 (Spring Boot集成)
spring boot·后端·sentry
黑客Jack4 小时前
属于网络安全规划重安全性需求
安全·web安全·php
夏天的味道٥4 小时前
使用 Java 执行 SQL 语句和存储过程
java·开发语言·sql
冰糖码奇朵5 小时前
大数据表高效导入导出解决方案,mysql数据库LOAD DATA命令和INTO OUTFILE命令详解
java·数据库·sql·mysql
好教员好5 小时前
【Spring】整合【SpringMVC】
java·spring
浪九天6 小时前
Java直通车系列13【Spring MVC】(Spring MVC常用注解)
java·后端·spring
堕落年代7 小时前
Maven匹配机制和仓库库设置
java·maven
功德+n7 小时前
Maven 使用指南:基础 + 进阶 + 高级用法
java·开发语言·maven
暴躁的小胡!!!7 小时前
Linux权限维持之协议后门(七)
linux·运维·服务器·网络·安全
随风九天7 小时前
Spring Boot + MyBatis + MySQL:快速搭建CRUD应用
spring boot·mysql·mybatis