spring boot 基础 spring security 权限验证

一、spring security 介绍

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

 


二、准备

环境:jdk 1.8 、spring boot 2.0  、spring security 5.2

IDE:idea

 


三、创建项目

这里我们直接使用idea 来创建项目,点击file 选择new project  创建spring boot 项目 勾选web和security模块 如图所示

spring boot 基础 spring security 权限验证

spring boot 基础 spring security 权限验证


3.1 项目创建完成结果图如下:

spring boot 基础 spring security 权限验证

 

3.2 在pom中导入依赖

导入security 依赖 为了方便测试我们顺便导入thymeleaf 

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.nekohtml</groupId>
            <artifactId>nekohtml</artifactId>
            <version>1.9.22</version>
        </dependency>

  在application.properties 文件中加入以下代码 去除html5 标签验证

#设置不要缓存
spring.thymeleaf.cache=false
spring.thymeleaf.mode=LEGACYHTML5

3.3  设置配置文件 

创建一个SecurityDemoConfig 类继承WebSecurityConfigurerAdapter 并在类上面添加@Configuration @EnableWebSecurity

注解标记配置信息  重写 configure 方法

package com.px.security.security;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @Author: px
 * @Date: 2018/11/02 9:55
 * @Version 1.0
 */
@Configuration
@EnableWebSecurity
public class SecurityDemoConfig extends WebSecurityConfigurerAdapter {

    /**
     *   http 安全验证
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("**/css/**","**/images/**","**/img/**","*/js/**","*/plugins/**","/user/register")
                .permitAll()
                .and()
                .formLogin()
                .loginPage("/loginAdmin")
                .loginProcessingUrl("/login")
                //登录成功 默认跳转url
                .defaultSuccessUrl("/admin")
                .successForwardUrl("/admin")
                //登录失败跳转url
                .failureUrl("/loginAdmin")
                .permitAll()
                .and()
                .csrf().disable()
                //frame 拒绝请求问题
                .headers()
                .frameOptions()
                .disable()
                //登出相关
                .and()
                .logout()
                //注销跳转url
                .logoutSuccessUrl("/loginAdmin")
                .permitAll()
                //设置过期时间
                .and().rememberMe().tokenValiditySeconds(200000);
    }

    /**
     * 身份验证处理器
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       super.configure(auth);
    }

    /**
     * web 安全验证
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }


}

设置进入admin 路径下的需要管理ADMIN 权限才能进入

//配置admin 下的都需要 ADMIN 权限才能进入
.antMatchers("/admin/**")
.hasRole("ADMIN")
.formLogin()
.loginPage("/loginAdmin") //设置登录页面
.loginProcessingUrl("/login")  //登录 表单提交Action
//登录成功 默认跳转url
.defaultSuccessUrl("/admin")
.successForwardUrl("/admin")
//登录失败跳转url
.failureUrl("/loginAdmin")
.permitAll()   //标记登录界面都能访问

3.4 准备测试页面

创建login.html  页面很简单  注意一点 这里的action 要和你前面在SecurityDemoConfig  配置的一致

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录界面</title>
</head>
<body>
        <form method="post" action="/login">
            <p>用户名<input name="username"></p>

            <p>密码<input  type="password" name="password" /></p>

            <p><input  type="submit"  value="登 录"/></p>
        </form>
</body>
</html>

创建登录之后的界面 home.html 内容很简单 就一个欢迎语

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>管理员界面</title>
</head>
<body>
<h1>欢迎进入管理员界面</h1>
</body>
</html>

 

创建controller 

package com.px.security.security;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Author: px
 * @Date: 2018/11/2 16:45
 * @Version 1.0
 */
@Controller
public class HomeController {
    @RequestMapping("/loginAdmin")
    public String  loginAdmin()
    {
        return "login";
    }
    @RequestMapping("/admin")
    public String index()
    {
        return "admin/home";
    }
}

四、 测试

 以上步骤完成之后一个简单的权限验证已经完成了

准备测试 

为了方便我们在 application 配置一个用户名 并且给他赋予ADMIN权限

#配置security 用户名密码
spring.security.user.name=admin
spring.security.user.password=123456
spring.security.user.roles=ADMIN

在浏览器输入 

http://127.0.0.1:8000/admin 

会自动跳转到登录界面

spring boot 基础 spring security 权限验证

登录之后成功跳转到home界面 说明成功了

spring boot 基础 spring security 权限验证

 

这里我们演示 用户名是写到配置文件中的 实际开发一般是从数据库中读取的

如果要从其他渠道获取用户权限 我们要自定义UserDetaisService 进行权限验证 实现 loadUserByUsername方法即可

如果要动态配置url 路径对应的权限 需要完成自定义实现以下步骤 

权限资源 SecurityMetadataSource  实现 FilterInvocationSecurityMetadataSource 接口

权限决策 AccessDecisionManager  实现AccessDecisionManager 接口

 在config文件中装载bean 对象

 .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {

                    public <O extends FilterSecurityInterceptor> O postProcess(

                            O fsi) {

                        fsi.setSecurityMetadataSource(mySecurityMetadataSource());

                        fsi.setAccessDecisionManager(myAccessDecisionManager());

                        return fsi;

                    }

                });