当前位置: 首页 > 面试题库 >

如何为Spring Boot项目添加基于方法的安全性?

高宏峻
2023-03-14
问题内容

我想在Spring Boot项目中添加基于方法的安全性。

似乎我只需要添加PermissionEvaluatorMethodSecurityExpressionHandlerbean,WebSecurityConfigurerAdapter@EnableGlobalMethodSecurity(prePostEnabled = true)和注释方法@PreAuthorize("isAuthenticated() and hasPermission(#param, 'somePermissionName')")

但是加入PermissionEvaluator豆子之后

@Bean
public PermissionEvaluator permissionEvaluator() {
    HelloPermissionEvaluator bean = new HelloPermissionEvaluator();
    return bean;
}

我得到一个消息IllegalArgumentException:“配置默认的servlet处理需要ServletContext”:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.HandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping()] threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:597)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1094)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:989)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at com.domain.simple.Application.main(Application.java:14)
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.web.servlet.HandlerMapping org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping()] threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
    ... 17 more
Caused by: java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
    at org.springframework.util.Assert.notNull(Assert.java:112)
    at org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer.<init>(DefaultServletHandlerConfigurer.java:54)
    at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.defaultServletHandlerMapping(WebMvcConfigurationSupport.java:346)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7f296e3.CGLIB$defaultServletHandlerMapping$26(<generated>)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7f296e3$$FastClassBySpringCGLIB$$48c20692.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration$$EnhancerBySpringCGLIB$$d7f296e3.defaultServletHandlerMapping(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
    ... 18 more

我在网上可以找到的所有内容都与jUnit测试有关。为什么会引发此异常?我想念什么?我是否必须添加一个ServletContext
bean,如果需要,如何添加?

我的要求是Gradle,Spring Boot和java config(而不是XML config)。最小和完整的来源如下:

应用程序

package com.domain.simple;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@EnableAutoConfiguration
@Configuration
@ComponentScan
public class Application {

    public static void main(String[] args) throws Throwable {
        SpringApplication.run(Application.class, args);
    }

}

HelloController.java

package com.domain.simple;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {

    Logger log = LoggerFactory.getLogger(HelloController.class);

    // @PreAuthorize("isAuthenticated() and hasPermission(#param, 'somePermissionName')")
    @RequestMapping(value = "/hello/{param}")
    @ResponseBody
    public String hello(@PathVariable("param") String param) {
        log.info("hello(" + param + ") called");
        return "Hello " + param;
    }
}

HelloPermissionEvaluator.java

package com.domain.simple;

import java.io.Serializable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;

public class HelloPermissionEvaluator implements PermissionEvaluator {

    Logger log = LoggerFactory.getLogger(HelloPermissionEvaluator.class);

    @Override
    public boolean hasPermission(Authentication authentication,
            Object targetDomainObject, Object permission) {
        log.info("hasPermission(Authentication, Object, Object) called");
        return true;
    }

    @Override
    public boolean hasPermission(Authentication authentication,
            Serializable targetId, String targetType, Object permission) {
        log.error("hasPermission(Authentication, Serializable, String, Object) called");
        throw new RuntimeException("ID based permission evaluation currently not supported.");
    }
}

WebSecurityConfig.java

package com.domain.simple;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@ComponentScan
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder authManagerBuilder)
            throws Exception {
        authManagerBuilder.inMemoryAuthentication().withUser("user")
                .password("password").roles("USER");
    }

//    @Bean
//    public MethodSecurityExpressionHandler expressionHandler() {
//        DefaultMethodSecurityExpressionHandler bean = new DefaultMethodSecurityExpressionHandler();
//        bean.setPermissionEvaluator(permissionEvaluator());
//        return bean;
//    }

    // this causes an IllegalArgumentException ("A ServletContext is required to configure default servlet handling")
    @Bean
    public PermissionEvaluator permissionEvaluator() {
        HelloPermissionEvaluator bean = new HelloPermissionEvaluator();
        return bean;
    }

}

build.gradle

buildscript {
    repositories {
        maven { url "http://repo.spring.io/libs-snapshot" }
        mavenLocal()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.0.2.RELEASE")
    }
}

apply plugin: 'eclipse'
apply plugin: 'java'
apply plugin: 'spring-boot'

jar {
    baseName = 'simple'
    version =  '0.1.0'
}

repositories {
    mavenCentral()
    maven { url "http://repo.spring.io/libs-snapshot" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-security")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.12'
}

问题答案:

尝试将放在PermissionEvaluator单独的@Configuration类中。您似乎在强迫它ServletContext准备就绪之前将其实例化(必须尽早创建Spring
Security过滤器,这样才可能发生)。



 类似资料:
  • 我想在Spring Boot项目中添加基于方法的安全性。 看来我需要的只是添加和bean,用注释我的和用方法。 HelloController.java hellopermissionevaluator.java WebSecurityConfig.java

  • 我添加了基于方法的安全性和角色层次结构。我在构建过程中不断遇到以下异常: 组织。springframework。豆。BeanInstationException:未能实例化[org.springframework.web.servlet.HandlerMapping]:工厂方法“defaultServletHandlerMapping”引发异常;嵌套的例外是java。lang.IllegalArg

  • 问题内容: 我正在使用create-react-app,但不喜欢。 目前尚不清楚通过@ font-face导入并本地加载的字体应该放在哪里。 即我正在加载 有什么建议么? -编辑 包括丹在回答中提到的要点 问题答案: 有两种选择: 使用导入 这是建议的选项。它可以确保字体通过构建管道,在编译过程中散列,以便浏览器缓存正常工作,并且在缺少文件的情况下得到编译错误。 如“添加图像,字体和文件”中所述,

  • 我试图在spring boot应用程序中添加一个环境变量。属性文件。我知道如何在非spring启动项目中正常添加它,但我找不到用于添加环境变量的字段,这就是我所看到的。 这是我的application.properties文件,这可能会有帮助。

  • 我有一个web应用程序+一组使用Spring创建的rest API。它本质上是一些html页面向rest服务器发送ajax请求。结构看起来有点像这样: 相同的凭据可用于静态内容和rest调用。 用户可以通过登录页登录,对于进一步的rest调用,可以使用某种令牌或从服务器返回的东西。 我已经检查了rest API的Spring Security方案,并找到了一些关于静态内容安全的资源,但无法找到如何

  • 本文向大家介绍为SpringBoot服务添加HTTPS证书的方法,包括了为SpringBoot服务添加HTTPS证书的方法的使用技巧和注意事项,需要的朋友参考一下 HTTPS是HTTP的安全版本,旨在提供数据传输层安全性(TLS)。当你的应用不使用HTTP协议的时候,浏览器地址栏就会出现一个不安全的提示。HTTPS加密每个数据包以安全方式进行传输,并保护敏感数据免受窃听者或黑客的攻击。 您可以通过