修改Spring @RolesAllowed的行为

时间:2015-09-01 02:26:32

标签: java spring spring-mvc spring-security spring-annotations

我使用Spring 2015-09-01 12:02:43.976 App Name[91111:2205337] Unknown class ContactPage in Interface Builder file. 2015-09-01 12:02:44.078 App Name[91111:2205337] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x7ff781d0a110> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key Message.' *** First throw call stack: ( 0 CoreFoundation 0x00000001051a99b5 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x00000001071ffdeb objc_exception_throw + 48 2 CoreFoundation 0x00000001051a95f9 -[NSException raise] + 9 3 Foundation 0x0000000105573fdb -[NSObject(NSKeyValueCoding) setValue:forKey:] + 288 4 UIKit 0x0000000105f9c418 -[UIViewController setValue:forKey:] + 88 5 UIKit 0x00000001061af2c7 -[UIRuntimeOutletConnection connect] + 109 6 CoreFoundation 0x00000001050ea590 -[NSArray makeObjectsPerformSelector:] + 224 7 UIKit 0x00000001061adcaa -[UINib instantiateWithOwner:options:] + 1864 8 UIKit 0x0000000105fa2df4 -[UIViewController _loadViewFromNibNamed:bundle:] + 381 9 UIKit 0x0000000105fa3720 -[UIViewController loadView] + 178 10 UIKit 0x0000000105fa3a22 -[UIViewController loadViewIfRequired] + 138 11 UIKit 0x0000000105fa4054 -[UIViewController view] + 27 12 UIKit 0x00000001066d36d2 -[_UIFullscreenPresentationController _setPresentedViewController:] + 87 13 UIKit 0x0000000105f74a4e -[UIPresentationController initWithPresentedViewController:presentingViewController:] + 133 14 UIKit 0x0000000105fb65ca -[UIViewController _presentViewController:withAnimationController:completion:] + 3736 15 UIKit 0x0000000105fb94b3 -[UIViewController presentViewController:animated:completion:] + 343 16 UIKit 0x00000001064eee8b __67-[UIStoryboardModalSegueTemplate newDefaultPerformHandlerForSegue:]_block_invoke + 243 17 UIKit 0x00000001064dd523 -[UIStoryboardSegueTemplate _perform:] + 449 18 UIKit 0x00000001064dd5ea -[UIStoryboardSegueTemplate perform:] + 156 19 UIKit 0x0000000105e1f522 -[UIApplication sendAction:to:from:forEvent:] + 92 20 UIKit 0x0000000105f7ec06 -[UIControl sendAction:to:forEvent:] + 67 21 UIKit 0x0000000105f7eeac -[UIControl _sendActionsForEvents:withEvent:] + 273 22 UIKit 0x0000000105f7e008 -[UIControl touchesEnded:withEvent:] + 601 23 UIKit 0x0000000105e8715f -[UIWindow _sendTouchesForEvent:] + 835 24 UIKit 0x0000000105e87d4d -[UIWindow sendEvent:] + 865 25 UIKit 0x0000000105e3c2ae -[UIApplication sendEvent:] + 263 26 UIKit 0x0000000105e1836c _UIApplicationHandleEventQueue + 6693 27 CoreFoundation 0x00000001050d5b21 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 28 CoreFoundation 0x00000001050cba4c __CFRunLoopDoSources0 + 556 29 CoreFoundation 0x00000001050caf03 __CFRunLoopRun + 867 30 CoreFoundation 0x00000001050ca918 CFRunLoopRunSpecific + 488 31 GraphicsServices 0x000000010acdcad2 GSEventRunModal + 161 32 UIKit 0x0000000105e1d99e UIApplicationMain + 171 33 App Name 0x0000000104fa749d main + 109 34 libdyld.dylib 0x0000000107d6492d start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb) 来保护我的API(方法),但我想改变从未经授权的用户调用方法时会发生什么。当前的行为是Spring抛出HTTP 403错误。这很好,但我只想在403响应的主体中添加一个额外的错误代码,以便能够区分不同场景中的访问被拒绝错误。

我很难弄清楚@RolesAllowed注释的实现位置。有没人遇到过它?或试图修改其行为?

我的控制器中的方法目前如下所示:

@RolesAllowed

2 个答案:

答案 0 :(得分:1)

您尝试做的事情可以在不修改注释的情况下完成。

在Spring配置中,您可以指定一个AccessDeniedHandler bean,当Spring Security确定您的用户不允许执行他们尝试执行的操作时,将调用该bean。

访问被拒绝处理程序非常简单:

public class CustomDefaultAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
        AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

}

AuthenticationProvider的一个示例,它为您提供有关失败的更多信息:

public class CustomAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private UserService userService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
        String username = String.valueOf(auth.getPrincipal().toString());
        String password = String.valueOf(auth.getCredentials());

        if(username.isEmpty() || password.isEmpty()){
            throw new UsernameNotFoundException("You pudding, there is no username or password");
        } else {
            SystemUser user = userService.findByUsername(username);
            if(user == null){
                throw new UsernameNotFoundException("No user exists, stop hacking");
            }
            //Do more stuff here to actually apply roles to the AuthToken etc
            return new UsernamePasswordAuthenticationToken(username, null, authorities);

        }
    }
}

答案 1 :(得分:0)

另一种方法是使用异常处理程序类和@ExceptionHandler批注。

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(AccessDeniedException.class)
    public ResponseEntity<?> handleAccessDenied(HttpServletRequest request, AccessDeniedException ex) {

        // exception handling logic
        if (request.getUserPrincipal() == null) {
            // user is not logged in
        } else {
            // user is logged in but doesn't have permission to the requested resource
        }

        // return whatever response you'd like
        return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
    }

}