SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理

本文源码:GitHub·点这里 || GitEE·点这里

一、Security简介

1、基础概念

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring的IOC,DI,AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为安全控制编写大量重复代码的工作。

2、核心API解读

1)、SecurityContextHolder

最基本的对象,保存着当前会话用户认证,权限,鉴权等核心数据。SecurityContextHolder默认使用ThreadLocal策略来存储认证信息,与线程绑定的策略。用户退出时,自动清除当前线程的认证信息。

初始化源码:明显使用ThreadLocal线程。

private static void initialize() {
    if (!StringUtils.hasText(strategyName)) {
        strategyName = "MODE_THREADLOCAL";
    }
    if (strategyName.equals("MODE_THREADLOCAL")) {
        strategy = new ThreadLocalSecurityContextHolderStrategy();
    } else if (strategyName.equals("MODE_INHERITABLETHREADLOCAL")) {
        strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
    } else if (strategyName.equals("MODE_GLOBAL")) {
        strategy = new GlobalSecurityContextHolderStrategy();
    } else {
        try {
            Class<?> clazz = Class.forName(strategyName);
            Constructor<?> customStrategy = clazz.getConstructor();
            strategy = (SecurityContextHolderStrategy)customStrategy.newInstance();
        } catch (Exception var2) {
            ReflectionUtils.handleReflectionException(var2);
        }
    }
    ++initializeCount;
}

2)、Authentication

源代码

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

源码分析

1)、getAuthorities,权限列表,通常是代表权限的字符串集合;
2)、getCredentials,密码,认证之后会移出,来保证安全性;
3)、getDetails,请求的细节参数;
4)、getPrincipal, 核心身份信息,一般返回UserDetails的实现类。

3)、UserDetails

封装了用户的详细的信息。

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}

4)、UserDetailsService

实现该接口,自定义用户认证流程,通常读取数据库,对比用户的登录信息,完成认证,授权。

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

5)、AuthenticationManager

认证流程顶级接口。可以通过实现AuthenticationManager接口来自定义自己的认证方式,Spring提供了一个默认的实现,ProviderManager。

public interface AuthenticationManager {
    Authentication authenticate(Authentication var1) throws AuthenticationException;
}

二、与SpringBoot2整合

1、流程描述

1)、三个页面分类,page1、page2、page3
2)、未登录授权都不可以访问
3)、登录后根据用户权限,访问指定页面
4)、对于未授权页面,访问返回403:资源不可用

2、核心依赖

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

3、核心配置

/**
 * EnableWebSecurity注解使得SpringMVC集成了Spring Security的web安全支持
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 权限配置
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置拦截规则
        http.authorizeRequests().antMatchers("/").permitAll()
                 .antMatchers("/page1/**").hasRole("LEVEL1")
                 .antMatchers("/page2/**").hasRole("LEVEL2")
                 .antMatchers("/page3/**").hasRole("LEVEL3");
        // 配置登录功能
        http.formLogin().usernameParameter("user")
                .passwordParameter("pwd")
                .loginPage("/userLogin");
        // 注销成功跳转首页
        http.logout().logoutSuccessUrl("/");
        //开启记住我功能
        http.rememberMe().rememberMeParameter("remeber");
    }
    /**
     * 自定义认证数据源
     */
    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception{
        builder.userDetailsService(userDetailService())
                .passwordEncoder(passwordEncoder());
    }
    @Bean
    public UserDetailServiceImpl userDetailService (){
        return new UserDetailServiceImpl () ;
    }
    /**
     * 密码加密
     */
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /*
     * 硬编码几个用户
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("spring").password("123456").roles("LEVEL1","LEVEL2")
                .and()
                .withUser("summer").password("123456").roles("LEVEL2","LEVEL3")
                .and()
                .withUser("autumn").password("123456").roles("LEVEL1","LEVEL3");
    }
    */
}

4、认证流程

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    @Resource
    private UserRoleMapper userRoleMapper ;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 这里可以捕获异常,使用异常映射,抛出指定的提示信息
        // 用户校验的操作
        // 假设密码是数据库查询的 123
        String password = "$2a$10$XcigeMfToGQ2bqRToFtUi.sG1V.HhrJV6RBjji1yncXReSNNIPl1K";
        // 假设角色是数据库查询的
        List<String> roleList = userRoleMapper.selectByUserName(username) ;
        List<GrantedAuthority> grantedAuthorityList = new ArrayList<>() ;
        /*
         * Spring Boot 2.0 版本踩坑
         * 必须要 ROLE_ 前缀, 因为 hasRole("LEVEL1")判断时会自动加上ROLE_前缀变成 ROLE_LEVEL1 ,
         * 如果不加前缀一般就会出现403错误
         * 在给用户赋权限时,数据库存储必须是完整的权限标识ROLE_LEVEL1
         */
        if (roleList != null && roleList.size()>0){
            for (String role : roleList){
                grantedAuthorityList.add(new SimpleGrantedAuthority(role)) ;
            }
        }
        return new User(username,password,grantedAuthorityList);
    }
}

5、测试接口

@Controller
public class PageController {
    /**
     * 首页
     */
    @RequestMapping("/")
    public String index (){
        return "home" ;
    }
    /**
     * 登录页
     */
    @RequestMapping("/userLogin")
    public String loginPage (){
        return "pages/login" ;
    }
    /**
     * page1 下页面
     */
    @PreAuthorize("hasAuthority(‘LEVEL1‘)")
    @RequestMapping("/page1/{pageName}")
    public String onePage (@PathVariable("pageName") String pageName){
        return "pages/page1/"+pageName ;
    }
    /**
     * page2 下页面
     */
    @PreAuthorize("hasAuthority(‘LEVEL2‘)")
    @RequestMapping("/page2/{pageName}")
    public String twoPage (@PathVariable("pageName") String pageName){
        return "pages/page2/"+pageName ;
    }
    /**
     * page3 下页面
     */
    @PreAuthorize("hasAuthority(‘LEVEL3‘)")
    @RequestMapping("/page3/{pageName}")
    public String threePage (@PathVariable("pageName") String pageName){
        return "pages/page3/"+pageName ;
    }
}

6、登录界面

这里要和Security的配置文件相对应。

<div align="center">
    <form th:action="@{/userLogin}" method="post">
        用户名:<input name="user"/><br>
        密&nbsp;&nbsp;&nbsp;码:<input name="pwd"><br/>
        <input type="checkbox" name="remeber"> 记住我<br/>
        <input type="submit" value="Login">
    </form>
</div>

三、源代码地址

GitHub·地址
https://github.com/cicadasmile/middle-ware-parent
GitEE·地址
https://gitee.com/cicadasmile/middle-ware-parent

原文地址:https://blog.51cto.com/14439672/2435635

时间: 2024-10-11 00:56:33

SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理的相关文章

springboot2.0整合springsecurity前后端分离进行自定义权限控制

在阅读本文之前可以先看看springsecurity的基本执行流程,下面我展示一些核心配置文件,后面给出完整的整合代码到git上面,有兴趣的小伙伴可以下载进行研究 使用maven工程构建项目,首先需要引入最核心的依赖, <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <

2_MVC+EF+Autofac(dbfirst)轻型项目框架_用户权限验证

前言 接上面两篇 0_MVC+EF+Autofac(dbfirst)轻型项目框架_基本框架 与 1_MVC+EF+Autofac(dbfirst)轻型项目框架_core层(以登陆为例) .在第一篇中介绍了此架构的基本分层,在第二篇中,以登陆功能为例,介绍了项目的代码结构.在本篇中将通过过滤器实现用户权限验证功能. 同样,文中有问题的地方欢迎批评指正!谢谢! 开发背景  在一个常规系统中权限验证是不可缺的,在较简单的系统中,用户只会被简单归为登陆用户和游客,而在较为复杂的系统中,除了判断用户是否登

SpringBoot2.0应用(三):SpringBoot2.0整合RabbitMQ

如何整合RabbitMQ 1.添加spring-boot-starter-amqp <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> 2.添加配置 spring.rabbitmq.host=localhost spring.rabbitmq.po

SpringBoot2.0整合fastjson的正确姿势

SpringBoot2.0如何集成fastjson?在网上查了一堆资料,但是各文章的说法不一,有些还是错的,可能只是简单测试一下就认为ok了,最后有没生效都不知道.恰逢公司项目需要将JackSon换成fastjson,因此自己来实践一下SpringBoot2.0和fastjson的整合,同时记录下来方便自己后续查阅. 一.Maven依赖说明 SpringBoot的版本为: <version>2.1.4.RELEASE</version> 在pom文件中添加fastjson的依赖:

springboot学习入门简易版五---springboot2.0整合jsp(11)

springboot对jsp支持不友好,内部tomcat对jsp不支持,需要使用外部tomcat,且必须打包为war包. 1 创建maven项目 注意:必须为war类型,否则找不到页面. 且不要把jsp页面存放在resources(原因:可能被别人访问,其次不在classes类路径中),因此,一般自行创建目录存放(一般/WEB-INF/下.  2 pom文件 <packaging>war</packaging> <!-- 注意为war包!!! --> <!-- s

springboot2.0整合logback日志(详细)

一. 近期自己的项目想要一个记录日志的功能,而springboot本身就内置了日志功能,然而想要输入想要的日志,并且输出到磁盘,然后按天归档,或者日志的切分什么的,自带的日志仅仅具有简单的功能,百度了一番,总结如下,适合大多数的应用场景 二. springboot的pom文件都会引一个parent <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-star

springboot2.0整合es的异常总结

异常: availableProcessors is already set to [4], rejecting [4] 在启动类中加入 System.setProperty("es.set.netty.runtime.available.processors", "false"); 异常:org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes

springboot2.0整合freemarker springboot日期转换器

pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> application.properties #viewResovler#spring.mvc.view.prefix=/WEB-INF/pages/#spring.m

springboot2.0整合freemarker快速入门

目录 1. 快速入门 1.1 创建工程pom.xml文件如下 1.2 编辑application.yml 1.3 创建模型类 1.4 创建模板 1.5 创建controller 1.6 测试 2. FreeMarker 基础 2.1 数据模型 2.2 List指令 2.3 遍历Map数据 2.4 if指令 2.5 运算符 2.6 空值处理 2.7 内建函数 freemarker是一个用Java开发的模板引擎 常用的java模板引擎还有哪些? Jsp.Freemarker.Thymeleaf .V