Spring Security基於類和方法授權操作及異常頁面的處理


頂部引入標簽庫:

  <%@taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

在需要面對不同權限的用戶展示不同數據處添加:

<security:authorize access="hasAnyRole('ROLE_PRODUCT', 'ROLE_ADMIN')">
            <li id="system-setting"><a
                    href="${pageContext.request.contextPath}/product/findAll">
                <i class="fa fa-circle-o"></i> 產品管理
            </a></li>
        </security:authorize>
        <security:authorize access="hasAnyRole('ROLE_ORDER', 'ROLE_ADMIN')">
            <li id="system-setting"><a
                    href="${pageContext.request.contextPath}/order/findAll">
                <i class="fa fa-circle-o"></i> 訂單管理
            </a></li>
        </security:authorize>

經過上面的操作,僅僅是對不同權限的用戶顯示不同的按鈕,實際上權限並沒有控制住,用戶可以通過地址欄手動輸入需要訪問的地址,從而訪問不在他權限范圍內的數據

總結:頁面動態菜單的展示只是為了用戶體驗,並未真正控制權限!

授權操作:

  SpringSecurity可以通過注解的方式來控制類或者方法的訪問權限。需要開啟對應的注解支持,若注解放在controller類中,對應注解支持應該放在mvc配置文件中因為controller類是由mvc配置文件掃描並創建的(子容器),同理,注解放在service類中,對應注解支持應該放在spring(applicationContext或spring-security[父容器])配置文件中,與此同理的有spring聲明式事務控制。建議放在service類中,因為父容器不會被http請求訪問到,相對更安全一些,http請求只會訪問子容器,再由子容器訪問父容器,注意:父容器不能訪問子容器

  開啟授權的注解支持:這里演示三類注解,但實際開發中,用一類即可!

<!-- 開啟權限控制的注解支持
     secured-annotations:SpringSecurity內部的權限控制注解開關
     pre-post-annotations:spring指定的權限控制注解開關
     jsr250-annotations:開啟jsr250-api的注解,需要jsr250-api的jar包-->
    <security:global-method-security
            secured-annotations="enabled"
            pre-post-annotations="enabled"
            jsr250-annotations="enabled"/>

    jsr250-api的支持

<dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>

  在注解支持對應類或者方法上添加注解:

@Controller
// @Secured({"ROLE_PRODUCT", "ROLE_ADMIN"}) // SpringSecurity內部制定的注解
// @RolesAllowed({"ROLE_PRODUCT", "ROLE_ADMIN"}) // jsr250注解
@PreAuthorize("hasAnyRole('ROLE_PRODUCT', 'ROLE_ADMIN')") // spring的el表達式注解
@RequestMapping("/product")
public class ProductController {

    @RequestMapping("/findAll")
    public String findAll(){
        return "product-list";
    }
}
@Controller
@RequestMapping("/order")
public class OrderController {

    @Secured({"ROLE_ORDER", "ROLE_ADMIN"})
    @RequestMapping("/findAll")
    public String findAll(){
        return "order-list";
    }
}

  權限不足異常處理:每次權限不足都出現403頁面,着實難堪!

    方式一:在 spring-security.xml配置文件中處理(只能處理403異常,其他異常無法處理)

<security:http auto-config="true" use-expressions="true">
        <!--省略其它配置-->
        <!-- 處理403異常 -->
        <security:access-denied-handler error-page="/403.jsp"/>
    </security:http>

    方式二:在 web.xml中處理

<error-page>
        <error-code>403</error-code>
        <location>/403.jsp</location>
    </error-page>
<error-page>
        <error-code>404</error-code>
        <location>/404.jsp</location>
    </error-page>

    方式三:編寫異常處理器(建議使用)

      springmvc傳統方式:

@Component
public class HandlerControllerException implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        ModelAndView mv = new ModelAndView();
        if (e instanceof AccessDeniedException) {
            mv.setViewName("redirect:/403.jsp");
        } else {
            mv.setViewName("redirect:/500.jsp");
        }
        return mv;
    }
}

      更簡便方式:

@ControllerAdvice
public class HandlerControllerAdvice {

    // 只有出現AccessDeniedException異常才跳轉403.jsp頁面
    @ExceptionHandler(AccessDeniedException.class)
    public String handlerException(){
        return "redirect:/403.jsp";
    }

    @ExceptionHandler(RuntimeException.class)
    public String runtimeHandlerException(){
        return "redirect:/500.jsp";
    }

    @ExceptionHandler(Exception.class)
    public ModelAndView customException(Exception e) {
        ModelAndView mv = new ModelAndView();
        mv.addObject("message", e.getMessage());
        mv.setViewName("error");
        return mv;
    }
}

      在該類中,可以定義多個方法,不同的方法處理不同的異常,例如專門處理空指針的方法、專門處理數組越界的方法...,也可以直接像上面最后的代碼一樣,在一個方法中處理所有的異常信息。

      @ExceptionHandler 注解用來指明異常的處理類型,即如果這里指定為 NullpointerException,則數組越界異常就不會進到這個方法中來。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM