如果您想了解@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标注)
- @Autowire在Spring Security自定义身份验证提供程序中不起作用
- java – Spring Security的类型级别上的@PreAuthorize不能在方法级别被覆盖
- java – 如何告诉spring security仅为特定端口应用authorizeRequests?
- JUnit如何测试@PreAuthorize批注及其由spring MVC控制器指定的spring EL?
@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自定义身份验证提供程序中不起作用
我们有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不能在方法级别被覆盖
有没有办法扭转这个订单?我还没弄清楚.
编辑:
在方法级别,我只想授予对非注册用户的访问权限:
@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?
我们以官方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??
由于您要测试通过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?等更多相关知识的信息可以在本站进行查询。
本文标签: