GVKun编程网logo

@PreAuthorize批注在Spring Security中不起作用(spring标注)

21

如果您想了解@PreAuthorize批注在SpringSecurity中不起作用的相关知识,那么本文是一篇不可错过的文章,我们将对spring标注进行全面详尽的解释,并且为您提供关于@Autowir

如果您想了解@PreAuthorize批注在Spring Security中不起作用的相关知识,那么本文是一篇不可错过的文章,我们将对spring标注进行全面详尽的解释,并且为您提供关于@Autowire在Spring Security自定义身份验证提供程序中不起作用、java – Spring Security的类型级别上的@PreAuthorize不能在方法级别被覆盖、java – 如何告诉spring security仅为特定端口应用authorizeRequests?、JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL?的有价值的信息。

本文目录一览:

@PreAuthorize批注在Spring Security中不起作用(spring标注)

@PreAuthorize批注在Spring Security中不起作用(spring标注)

我发现了许多类似的问题,但都没有解决我的问题。我的问题是ROLE_USER可以访问的功能ROLE_ADMIN

我的spring-security.xml代码如下。

<beans xmlns="http://www.springframework.org/schema/beans"   xmlns:s="http://www.springframework.org/schema/security"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   xsi:schemaLocation="http://www.springframework.org/schema/beans                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                    http://www.springframework.org/schema/security                    http://www.springframework.org/schema/security/spring-security-3.0.xsd"><s:http auto-config="true" use-expressions="true">    <s:intercept-url pattern="/index.jsp" access="permitAll" />    <s:intercept-url pattern="/welcome*" access="hasRole(''ROLE_USER'')" />    <s:intercept-url pattern="/helloadmin*" access="hasRole(''ROLE_ADMIN'')" />    <s:form-login login-page="/login" default-target-url="/welcome"        authentication-failure-url="/loginfailed" />    <s:logout logout-success-url="/logout" /></s:http><s:authentication-manager>  <s:authentication-provider>    <s:user-service>        <s:user name="asif" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />        <s:user name="raheel" password="123456" authorities="ROLE_USER" />              </s:user-service>  </s:authentication-provider></s:authentication-manager>

当我添加<s:global-method-security pre-post-annotations="enabled"/>
我的代码时显示找不到资源错误,并且当我删除我的代码时成功执行但ROLE_USER可以访问ROLE_ADMIN函数

我的控制器功能是。

@PreAuthorize("hasRole(''ROLE_ADMIN'')")@RequestMapping(value="/delete", method = RequestMethod.GET)public String DeleteAll(ModelMap model, Principal principal ) {    org.springframework.security.core.userdetails.User activeUser = (org.springframework.security.core.userdetails.User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();    System.out.println("Active user is "+activeUser.getUsername()+"Authorities are "+activeUser.getAuthorities());    return "deleteUsers";}

答案1

小编典典

你应该有

<s:global-method-security pre-post-annotations="enabled"/>

如果您希望@PreAuthorize注释起作用。


回答评论:

看来您缺少spring-aop依赖性。

如果您正在使用Maven,则需要:

<dependency>    <groupId>org.springframework</groupId>    <artifactId>spring-aop</artifactId>    <version>${org.springframework.version}</version></dependency>

如果没有,你可以从这里拿到罐子。

@Autowire在Spring Security自定义身份验证提供程序中不起作用

@Autowire在Spring Security自定义身份验证提供程序中不起作用

我们有Spring MVC应用程序。我们正在尝试将Spring安全性集成到其中。

我们已经编写了自定义身份验证提供程序,它将执行身份验证工作。

以下是我的自定义身份验证提供程序的代码。

    public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

    @Autowired
    private AuthenticationService authenticationService;

    @Override
    public Authentication authenticate(Authentication authentication) {

        CustomAuthenticationToken auth = (CustomAuthenticationToken) authentication;

        String username = String.valueOf(auth.getPrincipal());
        String password = String.valueOf(auth.getCredentials());

        try {

            Users user = new User();
            user.setUsername(username);
            user.setPassword(PasswordUtil.encrypt(password));

            user = authenticationService.validateLogin(user);

            return auth;
        } catch (Exception e) {
            throw new BadCredentialsException("Username/Password does not match for " + username);
        }
    }

    @Override
    public boolean supports(Class<? extends Object> authentication) {
        return (CustomAuthenticationToken.class.isAssignableFrom(authentication));

    }
}

在这里,我在下一行获取NullpointerException

user = authenticationService.validateLogin(user);

不会在自定义身份验证提供程序中自动连接authenticationService。虽然相同的服务authenticationService在我的MVC控制器中以相同的方式自动接线。

这是因为身份验证提供程序是Spring安全组件吗?

下面是我的web.xml

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/myApp-security.xml
    </param-value>
</context-param>

<servlet>
    <servlet-name>myApp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/myApp-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myApp</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

编辑1:-

我在我的spring安全配置文件中添加了以下几行。

<beans:bean id="customAuthenticationProvider">
    <beans:property name="userDetailsService" ref="userDetailsService"/>   
</beans:bean>

请帮助如何在Spring安全组件中自动连接服务类?

java – Spring Security的类型级别上的@PreAuthorize不能在方法级别被覆盖

java – Spring Security的类型级别上的@PreAuthorize不能在方法级别被覆盖

我试图用类型级别的@PreAuthorize注释保护Controller,并尝试通过使用不同的@PreAuthorize注释某些方法来覆盖该行为.然而,问题是 Spring首先评估方法注释(grant access),然后评估类注释(拒绝访问).

有没有办法扭转这个订单?我还没弄清楚.

编辑:

在方法级别,我只想授予对非注册用户的访问权限:

@PreAuthorize("isAnonymous()")
@RequestMapping(value = "/create",method = RequestMethod.GET)
public String renderCreateEntity(ModelMap model) {
    return userService.renderCreateEntity(model);
}

但是,该控制器的标准应该是允许完全认证的用户:

@Controller
@RequestMapping(value = "/user")
@PreAuthorize("isFullyAuthenticated()")
public class UserController { [...] }

当调试逐步通过应用程序,我看到isAnonymous()被先评估,然后isFullyAuthenticated(),从而导致访问权限的授予,并立即拒绝访问.

解决方法

感谢您的所有回覆.
然而,答案是完全不同的:)

我把这个放在这里,万一别人有同样的问题.

我在@InitBinder注释方法中注册了一个自定义验证器.此绑定方法称为控制器上请求的方法调用.而且由于此绑定方法没有使用@PreAuthorize注释,所以请求被拒绝.

解决方案是注释绑定方法,如下所示:

@InitBinder
@PreAuthorize("permitAll")
public void initBinder(WebDataBinder binder) {
    binder.setValidator(validator);
}

然后,该方法从我的OP调用像预期一样.

java – 如何告诉spring security仅为特定端口应用authorizeRequests?

java – 如何告诉spring security仅为特定端口应用authorizeRequests?

我们以官方API在端口8080(在我们的虚拟网络之外映射到端口443上的普通HTTPS)的方式配置我们的新微服务(使用Spring-Boot),而一些管理功能在辅助HTTP上端口7979.这些只在虚拟网络中使用,用于监控,负载均衡等.

所有API访问都需要使用OAuth保护,而管理功能应该可以在网络内自由访问.所以我们以这种方式配置Spring安全性(http是一个HttpSecurity对象):

    http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
        .and()
        .authorizeRequests()
            .antMatchers("/info").anonymous()
            .antMatchers("/health").anonymous()

            .antMatchers(HttpMethod.GET,"/warehouses/**").access(oauthScopeRead)
            .antMatchers(HttpMethod.PUT,"/warehouses/**").access(oauthScopeWrite)

            .anyRequest().denyAll();

这对两个端口都有影响:/ info和/ health是未经授权的,而/ warehouses需要身份验证,其他一切也需要身份验证(返回401,但是在使用身份验证调用时,它返回403).

由于公共端口上没有/ info或/ health,因此未经授权的用户返回404,而其他所有用户返回401.我对此不满意并希望拥有

>在公共端口上,要求对所有内容进行身份验证(并且仅在经过身份验证后返回404或403)
>在管理端口上,根本不需要身份验证(对于不是其中一个配置端点的所有内容,返回404).

我在Spring Security Javadocs或reference documentation中找不到任何有关端口的信息.

我能在这做什么?

最佳答案
我找到了解决方案:

这里的authorizeRequests()方法返回一个ExpressionUrlAuthorizationConfigurer< HttpSecurity> .ExpressionInterceptUrlRegistry,它(从其祖先类AbstractRequestMatcherRegistry)旁边的一些antMatchers方法也是一个通用的requestMatchers()方法,它接受一个或多个RequestMatcher对象.事实证明这是我可以自己实现的界面:

/**
 * A request matcher which matches just a port.
 *
 * @param   port  the port to match.
 *
 * @return  the new matcher.
 */
private RequestMatcher forPort(final int port) {
    return (HttpServletRequest request) -> port == request.getLocalPort();
}

(这是Java 8语法,对于以前的Java版本,您必须在此处编写任何匿名类.)

虽然requestMatchers需要几个这样的匹配器,看起来它们通过OR连接(至少this example suggests这个),因此我使用AndRequestMatcher将它连接到路径的匹配器(和HTTP方法)).

最终代码如下所示:

@Value("${management.port}")
private int managementPort;

@Value("${server.port}")
private int apiPort;

/**
 * Configure scopes for specific controller/httpmethods/roles here.
 */
@Override
public void configure(final HttpSecurity http) throws Exception {
    //J-
    http
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER)
        .and()
        .authorizeRequests()
            .requestMatchers(forPortAndpath(managementPort,"/info")).anonymous()
            .requestMatchers(forPortAndpath(managementPort,"/health")).anonymous()

            .requestMatchers(forPortAndpath(apiPort,HttpMethod.GET,"/warehouses/**")).access(oauthScopeRead)
            .requestMatchers(forPortAndpath(apiPort,HttpMethod.PUT,"/warehouses/**")).access(oauthScopeWrite)

            .anyRequest().denyAll();
    //J+
}

/**
 * Creates a request matcher which only matches requests for a specific local port and path (using an
 * {@link AntPathRequestMatcher} for the path part).
 *
 * @param   port         the port to match
 * @param   pathPattern  the pattern for the path.
 *
 * @return  the new request matcher.
 */
private RequestMatcher forPortAndpath(final int port,@Nonnull final String pathPattern) {
    return new AndRequestMatcher(forPort(port),new AntPathRequestMatcher(pathPattern));
}

/**
 * Creates a request matcher which only matches requests for a specific local port,path and request method (using
 * an {@link AntPathRequestMatcher} for the path part).
 *
 * @param   port         the port to match
 * @param   pathPattern  the pattern for the path.
 * @param   method       the HttpMethod to match. Requests for other methods will not be matched.
 *
 * @return  the new request matcher.
 */
private RequestMatcher forPortAndpath(final int port,@Nonnull final HttpMethod method,new AntPathRequestMatcher(pathPattern,method.name()));
}

/**
 * A request matcher which matches just a port.
 *
 * @param   port  the port to match.
 *
 * @return  the new matcher.
 */
private RequestMatcher forPort(final int port) {
    return (HttpServletRequest request) -> { return port == request.getLocalPort(); };
}

这并没有完全反映这个问题:managementPort在这里只有“/ info”和“/ health”公共可达,而不是一切.

你可以用它

                 .requestMatchers(forPort(managementPort)).anonymous()

使这个端口完全未经授权.

JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL?

JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL?

如何解决JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL??

由于您要测试通过Spring AOP实现的功能,因此需要使用Spring TestContext框架针对应用程序上下文运行测试。

然后,使用最少的安全性配置创建基本测试:

abstract-security-test.xml

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider user-service-ref = "userService" />
</security:authentication-manager>

<security:global-method-security pre-post-annotations="enabled" />

<bean id = "userService"/>

AbstractSecurityTest.java

@ContextConfiguration("abstract-security-test.xml")
abstract public class AbstractSecurityTest {
    @Autowired
    private AuthenticationManager am;

    @After
    public void clear() {
        SecurityContextHolder.clearContext();
    }

    protected void login(String name, String password) {
        Authentication auth = new UsernamePasswordAuthenticationToken(name, password);
        SecurityContextHolder.getContext().setAuthentication(am.authenticate(auth));
    }
}

现在,您可以在测试中使用它:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(...)
public class CreatePostControllerSecurityTest extends AbstractSecurityTest {
    ...

    @Test
    @ExpectedException(AuthenticationCredentialsNotFoundException.class)
    public void testNoAuth() {
        controller.modifyContent(...);
    }

    @Test
    @ExpectedException(AccessDeniedException.class)
    public void testAccessDenied() {
        login("userWithoutAccessRight", "...");
        controller.modifyContent(...);
    }

    @Test
    public void testAuthOK() {
        login("userWithAccessRight", "...");
        controller.modifyContent(...);
    }
}

解决方法

我已经在Spring MVC Controller中定义了此方法:

@RequestMapping(value = "{id}/content",method=RequestMethod.POST)
@PreAuthorize("principal.user.userAccount instanceof T(com.anonym.model.identity.PedagoAccount) AND principal.user.userAccount.userId == #object.pedago.userId AND #form.id == #object.id")
public String modifyContent(@PathVariable("id") Project object,@Valid  @ModelAttribute("form") ProjectContentForm form) {
    ....
}

然后,在我的JUnit测试中,我想调用此方法并确保验证了PreAuthorize条件。但是,当我在JUnit测试中使用错误帐户设置用户主体时,没有错误,并且该方法完成了。似乎注释已被绕过。
但是,当我以正常方式(不进行测试)调用此方法时,会验证PreAuthorize。

如果可能的话,如何在junit测试中测试此批注以及如何在抛出异常时捕获异常?

谢谢,
尼古拉斯

今天关于@PreAuthorize批注在Spring Security中不起作用spring标注的介绍到此结束,谢谢您的阅读,有关@Autowire在Spring Security自定义身份验证提供程序中不起作用、java – Spring Security的类型级别上的@PreAuthorize不能在方法级别被覆盖、java – 如何告诉spring security仅为特定端口应用authorizeRequests?、JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL?等更多相关知识的信息可以在本站进行查询。

本文标签: