SpringBoot Security使用


Spring Boot Security 介绍

  1. Spring Security 是通过一层层 Filter 来处理 web 请求的
    在 Filter 组成的链条中,逐步完成认证和授权,发现异常则抛给异常处理器处理
    在这里插入图片描述

  2. 过滤器链中的核心概念

    springSecurityFilterChain
    Spring Security 的核心过滤器叫 springSecurityFilterChain,类型是 FilterChainProxy

    WebSecurity、HttpSecurity
    WebSecurity 构建了 FilterChainProxy 对象
    HttpSecurity 构建了 FilterChainProxy 中的一个 SecurityFilterChain

    WebSecurityConfiguration
    @EnableWebSecurity 注解,导入了 WebSecurityConfiguration 类
    WebSecurityConfiguration 中创建了建造者对象 WebSecurity 和核心过滤器 FilterChainProxy

  3. Spring Security 常用组件

    Authentication:认证接口,定义了认证对象的数据形式。
    SecurityContext:上下文对象,用来存储 Authentication
    SecurityContextHolder:用来访问 SecurityContext
    UserDetails:代表用户信息
    UserDetailsService:获取用户信息


一、前期环境搭建

我的测试用户Entiy结构是这样的
在这里插入图片描述

public class SchoolUser {

    private String userName;
    private String passWord;
    private List<SchoolUserRoles> roles;
}

---------------
public class SchoolUserRoles {

    private String coleName;
    private String coleCode;
    private List<SchoolUserPermission> permissions;
}

----------------
public class SchoolUserPermission {

    //权限名
    private String code;
    //权限类型
    private String type;
    //资源路径
    private String url;
}

以及一些Controller,具体代码以上传至码云(地址见文章末尾)

二、使用步骤

1.配置自己的UserDetailService规则

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
	//用来模拟数据库操作
    @Autowired
    private AuthenticationMapper authenticationMapper;


    //用于通过用户名获取用户数据. 返回 UserDetails 对象, 表示用户的核心信息 (用户名, 用户密码, 权限等信息)
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        //因为这里我使用的模拟数据,密码没有加密过,需要手动加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

        SchoolUser schoolUser = authenticationMapper.findRolesBySchoolUserName(s);

        if(null == schoolUser){
            throw new UsernameNotFoundException(s);
        }

        ArrayList<SimpleGrantedAuthority> authorities = new ArrayList<>();

        //获取角色
        for (SchoolUserRoles role : schoolUser.getRoles()) {
            //获取角色实际资源
            for (SchoolUserPermission permission : role.getPermissions()) {
                authorities.add(new SimpleGrantedAuthority(permission.getCode()));
            }
        }

        return new User(schoolUser.getUserName(),passwordEncoder.encode(schoolUser.getPassWord()),authorities);
    }
}

2.Security配置类

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启方法级别设置
public class MySecurity extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    //路径权限设置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                /*
                因为使用了方法级别权限设置,就不在这里设置拦截了
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3")

                */
                .antMatchers("/","/index","*.js","*.css").permitAll()
                .anyRequest().authenticated()
              .and()
                .formLogin().loginPage("/login").permitAll()
              .and()
                .logout().logoutUrl("/logout").logoutSuccessUrl("/index")
              .and()
                .csrf().disable();


    }

    //认证授权(赋予角色)
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(getBCryptPasswordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //静态资源过滤
        /*
        *  如果不进行静态资源过滤的话,点击登录按钮会因为加载js文件需要权限跳转到登录
        *  然后登录通过之后,因为Security默认是登录完成后,到达登录前没有权限的页面,所以会打开该js文件
        * */
        web.ignoring().antMatchers("/qinjiang/**");
    }

    @Bean
    public BCryptPasswordEncoder getBCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

3 路径设置

	@PreAuthorize("hasAuthority('vip1')")
    @RequestMapping("/level1/1")
    public String level(){
        return "/views/level1/1";
    }
	
	/*
		@PreAuthorize()内有许多方法可以设置权限
		hasRole  用户具备某个角色( 这里内部拼接ROLE_,所以如果想自定义角色,请加上ROLE_ )
		hasAuthority 类似与hasRole
		hasAnyRole 用户具备多个角色中任意一个即可
		hasAnyAuthority 类似于hasAnyRole
		... 这里不多讨论了
	*/

	//权限中必须有Vip2这个权限
	@PreAuthorize("hasAuthority('vip2')")
    @RequestMapping("/level2/1")
    public String level_1(){
        return "/views/level2/1";
    }

在这里插入图片描述

这里就简单使用了SpringBoot Security完成权限设置以及授权

源码地址

源代码地址: https://gitee.com/crazyheng/spring-boot-security


有些人可能一开始对于Role与Permission权限有点疑惑,只要记清楚一个要点:真实控制资源路径的还是权限,然后角色控制权限,再给用户赋予角色,从而达到权限控制,权限都是为了真实资源而服务的,不管怎么变,最终都是对真实资源进行设置。


总结

这只是简单的使用Security,接下我准备了解学习下,UserDetailService的底层工作流程,Security认证流程,以及@EnableGlobalMethodSecurity与@PreAuthorize等,在这里就不多讨论了,请读者自行网络学习源码了解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值