我也花了很多时间研究如何在没有身份验证的情况下实现自定义授权。
身份验证过程在我们的系统之外(基于单点登录)。我已经做到了,如下所述,它有效!!!(我相信还有很多其他更好的方法,但这种方法很适合我的场景)
场景:用户已通过外部系统的身份验证,并且授权所需的所有信息都存在于请求中
1.需要创建安全配置,启用全局方法安全性如下。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
class SpringWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(final HttpSecurity http) throws Exception {
}
}
2.) 实现 Spring PermissionEvaluator 来授权请求是被允许还是被拒绝
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
public boolean authorize(final String groups, final String role) {
boolean allowed = false;
System.out.println("Authorizing: " + groups + "...");
if (groups.contains(role)) {
allowed = true;
System.out.println(" authorized!");
}
return allowed;
};
@Override
public boolean hasPermission(final Authentication authentication, final Object groups, final Object role) {
return authorize((String) groups, (String) role);
};
@Override
public boolean hasPermission(final Authentication authentication, final Serializable targetId, final String targetType, final Object permission) {
return authorize((String) targetId, (String) permission);
};
}
3.) 添加 MethodSecurityConfig
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
return expressionHandler;
}
}
4.) 在您的控制器中添加@PreAuthorize,如下所示。在此示例中,用户的所有组都存在于请求标头中,键为“availableUserGroups”。然后将其传递给 CustomPermissionEvaluator 以验证授权。请注意,spring 会自动将 Authentication 对象传递给方法“hasPermission”。因此,如果您想加载用户并使用 spring 'hasRole' 方法进行检查,则可以使用它。
@PreAuthorize("hasPermission(#userGroups, 'ADMIN')")
@RequestMapping(value = "/getSomething")
public String getSomething(@RequestHeader(name = "availableUserGroups") final String userGroups) {
return "resource allowed to access";
}
处理其他场景: 1.)在您想要在执行授权之前加载用户的场景。您可以使用 spring预身份验证过滤器,并以类似的方式进行操作。示例链接: http: //www.learningthegoodstuff.com/2014/12/spring-security-pre-authentication-and.html