• Spring security用户URL权限之FilterSecurityInterceptor


    总:
    用户通过浏览器发送URL地址,由FilterSecurityInterceptor判断是否具有相应的访问权限。
    对于用户请求的方法权限,例如注解@PreAuthorize("hasRole('ADMIN')"),由MethodSecurityInterceptor判断
    两个拦截器都继承了AbstractSecurityInterceptor

    1. /*
    2. * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. package org.springframework.security.web.access.intercept;
    17. import java.io.IOException;
    18. import javax.servlet.Filter;
    19. import javax.servlet.FilterChain;
    20. import javax.servlet.FilterConfig;
    21. import javax.servlet.ServletException;
    22. import javax.servlet.ServletRequest;
    23. import javax.servlet.ServletResponse;
    24. import org.springframework.security.access.SecurityMetadataSource;
    25. import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
    26. import org.springframework.security.access.intercept.InterceptorStatusToken;
    27. import org.springframework.security.web.FilterInvocation;
    28. /**
    29. * Performs security handling of HTTP resources via a filter implementation.
    30. * 通过筛选器实现对HTTP资源的安全处理。
    31. * <p>
    32. * The <code>SecurityMetadataSource</code> required by this security interceptor is of
    33. * type {@link FilterInvocationSecurityMetadataSource}.
    34. * <p>
    35. *安全拦截器所需的SecurityMetadataSource类型是FilterInvocationSecurityMetadataSource
    36. *
    37. * Refer to {@link AbstractSecurityInterceptor} for details on the workflow.
    38. * </p>
    39. *
    40. * @author Ben Alex
    41. * @author Rob Winch
    42. */
    43. public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements
    44. Filter {
    45. // ~ Static fields/initializers
    46. // =====================================================================================
    47. private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
    48. // ~ Instance fields
    49. // ================================================================================================
    50. /**
    51. *securityMetadataSource 中包含了一个HashMap,map中保存了用户请求的Http.Method和相应的URL地址
    52. *例如在Spring boot中,可能是如下的配置,参考图1
    53. *securityMetadataSource中的内容,参考图2
    54. */
    55. private FilterInvocationSecurityMetadataSource securityMetadataSource;
    56. private boolean observeOncePerRequest = true;
    57. // ~ Methods
    58. // ========================================================================================================
    59. /**
    60. * Not used (we rely on IoC container lifecycle services instead)
    61. *
    62. * @param arg0 ignored
    63. *
    64. * @throws ServletException never thrown
    65. */
    66. public void init(FilterConfig arg0) throws ServletException {
    67. }
    68. /**
    69. * Not used (we rely on IoC container lifecycle services instead)
    70. */
    71. public void destroy() {
    72. }
    73. /**
    74. * Method that is actually called by the filter chain. Simply delegates to the
    75. * {@link #invoke(FilterInvocation)} method.
    76. *
    77. * @param request the servlet request
    78. * @param response the servlet response
    79. * @param chain the filter chain
    80. *
    81. * @throws IOException if the filter chain fails
    82. * @throws ServletException if the filter chain fails
    83. *
    84. *
    85. *通过责任链式调用,执行doFilter方法
    86. *FilterInvocation中保存了filter相关的信息,比如request,response,chain
    87. *通过invoke方法处理具体的url过滤
    88. */
    89. public void doFilter(ServletRequest request, ServletResponse response,
    90. FilterChain chain) throws IOException, ServletException {
    91. FilterInvocation fi = new FilterInvocation(request, response, chain);
    92. invoke(fi);
    93. }
    94. public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {
    95. return this.securityMetadataSource;
    96. }
    97. public SecurityMetadataSource obtainSecurityMetadataSource() {
    98. return this.securityMetadataSource;
    99. }
    100. public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {
    101. this.securityMetadataSource = newSource;
    102. }
    103. public Class<?> getSecureObjectClass() {
    104. return FilterInvocation.class;
    105. }
    106. public void invoke(FilterInvocation fi) throws IOException, ServletException {
    107. //获取当前http请求的地址,比如说“/login”
    108. if ((fi.getRequest() != null)
    109. && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
    110. && observeOncePerRequest) {
    111. // filter already applied to this request and user wants us to observe
    112. // once-per-request handling, so don't re-do security checking
    113. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    114. }
    115. else {
    116. // first time this request being called, so perform security checking
    117. if (fi.getRequest() != null) {
    118. fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
    119. }
    120. //这里做主要URL比对,将当前URL与securityMetadataSource(我们自己配置)中的URL过滤条件进行比对
    121. //首先判断当前URL是permit的还是需要验证的
    122. //若需要验证,尝试加载保存在SecurityContextHolder.getContext()中的已登录信息
    123. //调用AbstractSecurityInterceptor中的AccessDecisionManager对象的decide方法
    124. //如果对于配置中需要登录才可访问的URL,已经查找到登录信息,则执行下一个Filter
    125. InterceptorStatusToken token = super.beforeInvocation(fi);
    126. try {
    127. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    128. }
    129. finally {
    130. super.finallyInvocation(token);
    131. }
    132. super.afterInvocation(token, null);
    133. }
    134. }
    135. /**
    136. * Indicates whether once-per-request handling will be observed. By default this is
    137. * <code>true</code>, meaning the <code>FilterSecurityInterceptor</code> will only
    138. * execute once-per-request. Sometimes users may wish it to execute more than once per
    139. * request, such as when JSP forwards are being used and filter security is desired on
    140. * each included fragment of the HTTP request.
    141. *
    142. * @return <code>true</code> (the default) if once-per-request is honoured, otherwise
    143. * <code>false</code> if <code>FilterSecurityInterceptor</code> will enforce
    144. * authorizations for each and every fragment of the HTTP request.
    145. */
    146. public boolean isObserveOncePerRequest() {
    147. return observeOncePerRequest;
    148. }
    149. public void setObserveOncePerRequest(boolean observeOncePerRequest) {
    150. this.observeOncePerRequest = observeOncePerRequest;
    151. }
    152. }

  • 相关阅读:
    Google 商店:您的应用静态链接到的 OpenSSL 版本有多个安全漏洞。建议您尽快更新 OpenSSL
    android控件库(2)-仿Google Camera 的对焦效果
    新浪微博客户端(54)-代码重构-将宏定义修改为常量
    android自定义控件(1)-自定义控件属性
    新浪微博客户端(53)-记录用户最近点击表情
    android-解决EditText的inputType为Password时, 字体不一致的问题
    新浪微博客户端(52)-长按或滑动显示表情
    iOS- Terminating app due to uncaught exception 'NSRangeException'
    新浪微博客户端(51)-将表情图片转换为文本
    新浪微博客户端(50)-解决输入Emotion表情逐渐变小的问题
  • 原文地址:https://www.cnblogs.com/tilv37/p/7090506.html
Copyright © 2020-2023  润新知