简体   繁体   English

使用Spring Security'hasPermission()'对未经授权的REST服务请求返回JSON

[英]Return JSON on unauthorized REST service request using Spring Security 'hasPermission()'

I am implementing method level restriction/authorization (on REST services ) using Spring security. 我正在使用Spring安全性实现方法级别的限制/授权(在REST服务上 )。
I have used the spring expression language and implemented custom Expression Evaluator. 我已使用spring表达式语言并实现了自定义Expression Evaluator。

It is working fine for me. 对我来说很好。 However, if an unauthorized user tries to access the service, it is responding with a login page. 但是,如果未经授权的用户尝试访问该服务,它将以登录页面作为响应。 Since my application is REST based only , I want to return only JSON data for all the requests. 由于我的应用程序仅基于REST ,因此我只想为所有请求返回JSON数据。

How do I make it return JSON instead of the login page?(eg: {status : Denied} ) 如何使其返回JSON而不是登录页面?(例如: {status : Denied}

Here is the code Snippet: 这是代码段:

CustomEvaluator CustomEvaluator

public boolean hasPermission(Authentication authentication, Object userId, Object permissionId) {
        List<String> permList = new MyDAO().getPermissionsForUser((String) userId);
        if(permList.contains(((String) permissionId))){
            return true;
        }else{
            return false;
        }
    }

Service 服务

@PreAuthorize("hasPermission(#userId, '3')")
    public String testAuthorization(Object obj, String userId){

        System.out.println("Has access to the service method....");

        return  "success";
    }

Controller 控制者

public @ResponseBody String testAuthorization(Object o,@RequestParam("userId") String userId){
        System.out.println("User ID = "+userId);
        String abc = service.testAuthorization(o,userId);
        return "{\"status\":\"success\"}";
    }

spring-security.xml spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       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">


    <security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled">
        <security:expression-handler ref="expressionHandler"/>
    </security:global-method-security>

    <!-- This is where we configure Spring-Security  -->
    <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/auth/denied" >
        <security:intercept-url pattern="/auth/auth/login" access="permitAll"/>
        <security:intercept-url pattern="/auth/main/admin" access="hasRole('ROLE_ADMIN')"/>
        <security:intercept-url pattern="/auth/main/common" access="hasRole('ROLE_USER')"/>


    </security:http>

    <security:authentication-manager>
        <security:authentication-provider user-service-ref="customUserDetailsService">
            <security:password-encoder ref="passwordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
    <bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>

    <!-- A custom service where Spring will retrieve users and their corresponding access levels  -->
    <bean id="customUserDetailsService" class="com.cjl.security.service.CustomUserDetailsService"/>

    <bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="permissionEvaluator" ref="permissionEvaluator"/>
    </bean>

    <bean id="permissionEvaluator" class="com.cjl.security.evaluators.MethodPermissionEvaluator"/>


</beans>

What is happening is an AccessDeniedException is being thrown, so you want to configure your system to intercept that exception and instead return JSON. 正在发生的情况是抛出了AccessDeniedException ,因此您需要配置系统以拦截该异常并返回JSON。

You can set up an @ExceptionHandler method within your controller which catches the AccessDeniedException . 您可以在控制器内设置@ExceptionHandler方法,以捕获AccessDeniedException However, you probably want to do the same thing in all your controllers, so if you are using Spring 3.2, you can use @ControllerAdvice annotation on a separate 'advice' class and then include the @ExceptionHandler method in there. 但是,您可能想在所有控制器中执行相同的操作,因此,如果您使用的是Spring 3.2,则可以在单独的“ advice”类上使用@ControllerAdvice批注,然后在其中包含@ExceptionHandler方法。

@ControllerAdvice 
public class ExceptionControllerAdvice {

    @ExceptionHandler(AccessDeniedException.class)
    @ResponseBody
    public String exception(AccessDeniedException e) {
        return "{\"status\":\"access denied\"}";
    } 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM