Java 自定义安全表达式
我正在学习如何创建自定义安全表达式的教程,我创建了三个类,但我遇到了错误,我尝试了谷歌的一切,可能是我没有更新或一些。你能解释一下发生了什么事吗 错误:Java 自定义安全表达式,java,spring-boot,spring-security,Java,Spring Boot,Spring Security,我正在学习如何创建自定义安全表达式的教程,我创建了三个类,但我遇到了错误,我尝试了谷歌的一切,可能是我没有更新或一些。你能解释一下发生了什么事吗 错误: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentExcept
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression 'isComprador()'] with root cause
Method call: Method isComprador() cannot be found on type org.springframework.security.access.expression.method.MethodSecurityExpressionRoot
MethodSecurityConfig:
@配置
@EnableGlobalMethodSecurity(Prespenabled=true)
公共类方法SecurityConfig扩展了GlobalMethodSecurityConfiguration{
@凌驾
受保护的MethodSecurityExpressionHandler createExpressionHandler(){
返回新的CustomMethodSecurityExpressionHandler();
}
}
CustomMethodSecurityExpressionHandler:
公共类CustomMethodSecurityExpressionHandler扩展了DefaultMethodSecurityExpressionHandler{
私有最终身份验证trustResolver trustResolver=新身份验证TrustResolverImpl();
@凌驾
受保护的MethodSecurityExpressionOperations createSecurityExpressionRoot(身份验证、方法调用){
CustomMethodSecurityExpressionRoot=新的CustomMethodSecurityExpressionRoot(身份验证);
setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
返回根;
}
}
CustomMethodSecurityExpressionRoot:
公共类CustomMethodSecurityExpressionRoot扩展SecurityExpressionRoot实现MethodSecurityExpressionOperations{
私有对象过滤器对象;
私有对象返回对象;
私有对象目标;
公共CustomMethodSecurityExpressionRoot(身份验证){
超级(认证);
}
@凌驾
public void setFilterObject(对象filterObject){
this.filterObject=filterObject;
}
@凌驾
公共对象getFilterObject(){
返回过滤器对象;
}
@凌驾
public void setReturnObject(对象returnObject){
this.returnObject=returnObject;
}
@凌驾
公共对象getReturnObject(){
返回对象;
}
void setThis(对象目标){
this.target=目标;
}
@凌驾
公共对象getThis(){
回报目标;
}
//
公共布尔isComprador(){
final Usuario Usuario=((userdetailsimple)this.getPrincipal()).getUsuario();
返回usuario.getPerfil()==Perfil.compador;
}
公共布尔值isVendedor(){
final Usuario Usuario=((userdetailsimple)this.getPrincipal()).getUsuario();
返回usuario.getPerfil()==Perfil.VENDEDOR;
}
}
谢谢
收件人:,
Carlos Oliveira我真的建议使用自定义bean,而不是尝试集成到表达式根中。这更易于配置,只需创建一个简单的pojo即可将代码与Spring安全性分离,并使代码更加集中 要使用此方法,请从创建Springbean开始:
@Component
public class Authz {
public boolean isComprador() {
// Authentication is the currently logged in user
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication != null && "comprador".equals(authentication.getName());
}
}
然后可以使用@beanName.methodName
引用Bean中的方法。在我们的例子中,Bean名称是authz
,我们的方法是isComprador
,因此以下方法可以工作:
@Service
public class MessageService {
// we pass in the name argument into our custom expression Authz.isComprador
@PreAuthorize("@authz.isComprador()")
String greetForName(String name) {
return "Hello " + name;
}
}
最后,我们只需像正常情况一样启用方法安全性:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {
}
然后,您可以编写一些单元测试来证明它是有效的:
@SpringBootTest
class DemoApplicationTests {
@Autowired
MessageService service;
@Test
@WithMockUser // run the test as a user with the default username of user
void secureWhenForbidden() {
assertThatCode(() -> service.greetForName("Rob")).isInstanceOf(AccessDeniedException.class);
}
@Test
@WithMockUser("comprador") // run the test as a user with the username of comprador
void secureWhenGranted() {
assertThatCode(() -> service.greetForName("Rob")).doesNotThrowAnyException();;
}
}
您可以在上找到完整的样品,这是我想要的,非常简单,而且时间很短。我不敢相信,因为大多数人建议在表达式的根处集成它。