天道酬勤,学无止境

spring 4 中的自定义 ExceptionTranslationFilter 来处理 REST AuthenticationException(Custom ExceptionTranslationFilter in spring 4 to handle REST AuthenticationException)

问题

我有一个由 spring security 保护的 spring MVC RESTful 应用程序。 客户端是 Angular JS。 但是我的登录和注销页面是普通的 jsp,我执行基于表单的登录和注销。 成功完全认证后,我加载我的安全页面(它使用 anlgularJS 和 RESTful api)。

当调用 REST api 时,我需要帮助处理 AuthenticationException 和 AccessDeniedException。 我扩展了 ResponseEntityExceptionHandler 并且我能够捕获 AccessDEniedException 并抛出一个 json 响应。 我理解处理 AuthenticationException (所以我可以在休息完整请求的情况下停止 302 重定向)我需要扩展 ExceptionTranslationFilter。 我发现的大多数示例都使用 XML 配置。 但是可以在 Java config 中做吗?

我确实编写了一个组件来扩展 ExceptionTranslationFilter 并创建了一个自定义的 AuthenticationEntryPoint,但我不确定如何将它注入我的 ExceptionTranslationFilter

我收到一个错误,由:java.lang.IllegalArgumentException: authenticationEntryPoint must be specified 我尝试添加一个构造函数,但找不到 thors 方法。 任何帮助解决表示赞赏。

我的身份验证入口点

@Service
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2)
            throws IOException, ServletException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                "Unauthorized.");

    }

}

我的异常翻译过滤器

@Component
public class RestExceptionTranslationFilter extends ExceptionTranslationFilter {
    public static final Logger LOGGER = LoggerFactory.getLogger(RestExceptionTranslationFilter.class);

    @Override
    protected void sendStartAuthentication(HttpServletRequest req, HttpServletResponse resp, FilterChain chain, AuthenticationException reason)
            throws ServletException, IOException {

            boolean isAjax = "XMLHttpRequest".equals(req.getHeader("X-Requested-With"));

        if (isAjax) {

            String jsonObject = "{\"message\":\"Please login first.\"," + "\"access-denied\":true,\"cause\":\"AUTHENTICATION_FAILURE\"}";
                String contentType = "application/json";
                resp.setContentType(contentType);
                PrintWriter out = resp.getWriter();
                out.print(jsonObject);
                out.flush();
                out.close();
                return;
            }

        super.sendStartAuthentication(req, resp, chain, reason);
    }

}

安全配置

@Configuration
@EnableWebSecurity
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    public static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfig.class);

    @Autowired
    UserDetailsRepository userDetailsRepository;

    /**
     * In Memory Authentication
     * @param auth
     * @throws Exception
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsRepository);
    }


    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**");

    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        LOGGER.debug("Configuring Spring Security HttpSecurity...");
        http.authorizeRequests().antMatchers("/api/**").authenticated();
        http.authorizeRequests().antMatchers("/app.html").authenticated();
        http.authorizeRequests().antMatchers("/login**").permitAll();
        http.authorizeRequests().and().formLogin().loginProcessingUrl("/login").loginPage("/login.jsp").defaultSuccessUrl("/app.html").and()
            .authorizeRequests().and().logout().logoutUrl("/logout").logoutSuccessUrl("/logout.html").permitAll();
        http.csrf().disable();
    }

    @Bean
    public static ExceptionTranslationFilter exceptionTranslationFilter() {
        RestExceptionTranslationFilter exceptionTranslationFilter = new RestExceptionTranslationFilter(new RestAuthenticationEntryPoint());
        RestAccessDeniedHandler accessDeniedHandlerImpl = new RestAccessDeniedHandler();
        exceptionTranslationFilter.setAccessDeniedHandler(accessDeniedHandlerImpl);
        exceptionTranslationFilter.afterPropertiesSet();
        return exceptionTranslationFilter;
    }
}

错误日志

2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 8 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2015-01-14_23:10:17.270 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - doFilter -
                Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 9 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2015-01-14_23:10:17.270 DEBUG o.s.s.w.s.SessionManagementFilter - doFilter -
                Requested session ID CC2CA43BAE60F06F2431C9280A74081F is invalid.
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 10 of 12 in additional filter chain; firing Filter: 'RestExceptionTranslationFilter'
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2015-01-14_23:10:17.270 DEBUG o.s.security.web.FilterChainProxy - doFilter -
                /org/hmie/fms/sy/myAccount.html at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2015-01-14_23:10:17.270 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/login.jsp'
2015-01-14_23:10:17.270 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/login'
2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/logout.html'
2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/ess/partials/alertpopup.html'
2015-01-14_23:10:17.286 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/partials/alertpopup.html'
2015-01-14_23:10:17.287 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - matches -
                Checking match of request : '/org/hmie/fms/sy/myaccount.html'; against '/fms/**'
2015-01-14_23:10:17.287 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - beforeInvocation -
                Secure object: FilterInvocation: URL: /org/hmie/fms/sy/myAccount.html; Attributes: [authenticated]
2015-01-14_23:10:17.287 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - authenticateIfRequired -
                Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2015-01-14_23:10:17.287 DEBUG o.s.s.access.vote.AffirmativeBased - decide -
                Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5fcd184d, returned: -1
2015-01-14_23:10:17.298 DEBUG o.s.s.w.a.ExceptionTranslationFilter - handleSpringSecurityException -
                Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) ~[AffirmativeBased.class:3.2.4.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206) ~[AbstractSecurityInterceptor.class:3.2.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115) ~[FilterSecurityInterceptor.class:3.2.4.RELEASE]
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) ~[FilterSecurityInterceptor.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [ExceptionTranslationFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [ExceptionTranslationFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [SessionManagementFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [AnonymousAuthenticationFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) [SecurityContextHolderAwareRequestFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [RequestCacheAwareFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) [AbstractAuthenticationProcessingFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) [LogoutFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57) [HeaderWriterFilter.class:3.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [OncePerRequestFilter.class:4.0.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [SecurityContextPersistenceFilter.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) [WebAsyncManagerIntegrationFilter.class:3.2.4.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [OncePerRequestFilter.class:4.0.5.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) [FilterChainProxy$VirtualFilterChain.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) [FilterChainProxy.class:3.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [FilterChainProxy.class:3.2.4.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) [DelegatingFilterProxy.class:4.0.5.RELEASE]
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) [DelegatingFilterProxy.class:4.0.5.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.12]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.12]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.12]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.12]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:8.0.12]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.12]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.12]
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) [catalina.jar:8.0.12]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.12]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:534) [catalina.jar:8.0.12]
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081) [tomcat-coyote.jar:8.0.12]
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) [tomcat-coyote.jar:8.0.12]
    at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:222) [tomcat-coyote.jar:8.0.12]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1566) [tomcat-coyote.jar:8.0.12]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1523) [tomcat-coyote.jar:8.0.12]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_05]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_05]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.12]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_05]
回答1

即使您使用@Service 对其进行注释,Spring 也不会自动注入您的 AuthenticationEntryPoint。 您可以删除 @Service 注释并通过您的安全配置注入它,如下所示:

http.exceptionHandling()
    .authenticationEntryPoint(new MyAuthenticationEntryPoint())

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Spring Security筛选器链如何工作(How Spring Security Filter Chain works)
    问题 我意识到Spring安全性是建立在过滤器链上的,该过滤器将拦截请求,检测(不存在)身份验证,重定向到身份验证入口点或将请求传递给授权服务,并最终让该请求到达servlet或引发安全异常(未经身份验证或未经授权)。 DelegatingFitlerProxy将这些过滤器粘合在一起。 为了执行任务,这些筛选器访问服务,例如UserDetailsS​​ervice和AuthenticationManager 。 链中的关键过滤器为(按顺序) SecurityContextPersistenceFilter(从JSESSIONID恢复身份验证) UsernamePasswordAuthenticationFilter(执行身份验证) ExceptionTranslationFilter(从FilterSecurityInterceptor捕获安全异常) FilterSecurityInterceptor(可能会抛出身份验证和授权异常) 我很困惑如何使用这些过滤器。 难道对于Spring提供的form-login, UsernamePasswordAuthenticationFilter仅用于/ login ,而后面的过滤器不可用? 表单登录名称空间元素是否自动配置这些过滤器? 是否每个请求(无论是否经过身份验证)都到达非登录URL的FilterSecurityInterceptor
  • 在 Spring Security 中处理自定义异常(Handle Custom Exceptions in Spring Security)
    问题 我们正在使用 spring MVC + spring security + hibernate 创建一个 RESTful API。 API 可以生成 JSON 和 HTML。 为 spring 安全做一个好的错误处理让我很头疼: 身份验证可以通过多种方式进行:BasicAuth、通过 POST 请求中的不同参数以及通过 Web 登录。 对于每种身份验证机制,spring security xml 配置的<http>命名空间元素中都声明了一个过滤器。 我们在自定义的HandlerExceptionResolver处理所有的 spring 异常。 这适用于我们控制器中抛出的所有异常,但我不知道如何处理自定义 spring 安全过滤器中抛出的自定义异常。 由于 spring 安全过滤器在调用我们的任何控制器之前出现,因此我们看不到我们在自定义 spring 安全过滤器中抛出的异常。 我在 stackoverflow 上发现了这个问题:在 Spring Security 中使用自定义异常。 但是我不明白他们在哪里处理在那里抛出的异常。 我们尝试了这种方法,但是我们的自定义HandlerExceptionResolver没有被调用。 相反,用户会看到一个由 tomcat 渲染的丑陋的堆栈跟踪。 我们为什么需要这个? 可以激活和停用用户。 如果它们被停用并尝试执行某些操作
  • Spring Security开发安全的REST服务视频教程
    Spring security框架简介 1、简介 一个能够为基于Spring的企业应用系统提供声明式的安全訪问控制解决方式的安全框架(简单说是对访问权限进行控制嘛),应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。 spring security的主要核心功能为 认证和授权,所有的架构也是基于这两个核心功能去实现的。 2、框架原理 众所周知 想要对对Web资源进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。所以springSecurity在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全。 如下为其主要过滤器 WebAsyncManagerIntegrationFilter SecurityContextPersistenceFilter
  • Spring Security学习笔记
    1.特点 # 1.1认证方式 如果用户没有设置密码,则系统会自动生成一个密码在控制台打印。 参考UserDetailsServiceAutoConfiguration类中这段代码: package org.springframework.boot.autoconfigure.security.servlet; private String getOrDeducePassword(User user, PasswordEncoder encoder) { String password = user.getPassword(); if (user.isPasswordGenerated()) { logger.info(String.format("%n%nUsing generated security password: %s%n", user.getPassword())); } 生成密码的来源在SecurityProperties配置类中的静态内部类User里面: package org.springframework.boot.autoconfigure.security; private String name = "user"; private String password = UUID.randomUUID().toString(); 用户配置
  • REST 控制器中的 Spring Boot 绑定和验证错误处理(Spring Boot binding and validation error handling in REST controller)
    问题 当我有以下带有 JSR-303(验证框架)注释的模型时: public enum Gender { MALE, FEMALE } public class Profile { private Gender gender; @NotNull private String name; ... } 以及以下 JSON 数据: { "gender":"INVALID_INPUT" } 在我的 REST 控制器中,我想处理绑定错误( gender属性的枚举值无效)和验证错误( name属性不能为空)。 以下控制器方法不起作用: @RequestMapping(method = RequestMethod.POST) public Profile insert(@Validated @RequestBody Profile profile, BindingResult result) { ... } 在绑定或验证发生之前,这会com.fasterxml.jackson.databind.exc.InvalidFormatException序列化错误。 经过一番摆弄之后,我想出了这个自定义代码,它可以满足我的需求: @RequestMapping(method = RequestMethod.POST) public Profile insert(@RequestBody Map
  • 春季安全性:未经身份验证的授权(spring-security: authorization without authentication)
    问题 我正在尝试将Spring Security集成到我的Web应用程序中。 只要集成了身份验证和授权的整个过程,这似乎就很容易做到。 但是,身份验证和授权看起来是如此耦合,以至于我了解如何拆分这些过程以及独立于授权来获取身份验证非常耗时。 身份验证过程在我们系统的外部(基于单点登录),无法修改。 但是,一旦用户成功完成此过程,就会将其加载到会话中,包括角色。 我们正在尝试实现的是在Spring Security的授权过程中使用此信息,也就是说,强制它从用户会话中获取角色,而不是通过身份验证提供程序来获取。 有什么办法可以做到这一点? 回答1 如果已经使用SSO服务完成了身份验证,则应使用spring security的预身份验证过滤器之一。 然后,您可以指定一个UserDetails服务(可能是自定义的),该服务将使用预先认证的用户原则填充GrantedAuthority的 SpringSecurity包括几个预认证过滤器,包括J2eePreAuthenticatedProcessingFilter和RequestHeaderPreAuthenticatedProcessingFilter。 如果找不到适合自己的解决方案,那么只要您知道您的SSO实施在数据中填充的位置,就可以自己编写它,也没有那么困难。 (这取决于课程的实施。) 只需实现Filter接口
  • 如何使用 Spring Security / Spring MVC 处理表单登录(How to process a form login using Spring Security / Spring MVC)
    问题 简单的问题,我只需要一个指向正确方向的指针: 我有一个简单的 Spring MVC/Spring Security webapp。 最初,我设置了 Spring Security,以便默认登录页面正确显示和验证(我使用DaoAuthenticationProvider实现了UserDetailsService来执行此操作)。 下一步:用我的登录页面替换默认的 spring 登录页面并发布凭据。 但是我如何处理提交的登录凭据? 我假设我将表单发布到控制器,验证凭据,但我不清楚之后正确的步骤是什么。 例如: 我正在调用 AuthenticationManager 的方法吗? 我需要为此定义一个bean吗? 是否有我需要实现的接口/服务,例如 AuthenticationEntryPoint 之类的? 我已经阅读了 3 次文档,但并没有完全遵循它们。 我知道这很简单,所以我只需要了解流程应该如何进行。 回答1 Spring Security 参考文档概述了 5.4 Web 应用程序中的身份验证中的基本处理流程。 有第 6 点: 接下来,服务器将决定所提供的凭据是否有效。 如果它们有效,下一步就会发生。 如果它们无效,通常会要求您的浏览器重试(因此您返回到上面的第二步)。 ... Spring Security 有不同的类负责上述大部分步骤。 主要参与者(按使用顺序)是
  • Spring Security permitAll()不允许匿名访问(Spring Security permitAll() not allowing anonymous access)
    问题 我有一个单一的方法,我想允许匿名和身份验证的访问。 我正在使用基于Java配置的Spring Security 3.2.4。 被覆盖的configure方法(在我的自定义配置类中,扩展了WebSecurityConfigurerAdapter)具有以下http块: http .addFilterBefore(muiltpartFilter, ChannelProcessingFilter.class) .addFilterBefore(cf, ChannelProcessingFilter.class) .authorizeRequests() .anyRequest() .authenticated() .and() .authorizeRequests() .antMatchers("/ping**") .permitAll() .and() .formLogin() .loginPage("/login") .permitAll() .and() .logout() .logoutUrl("/logout") .logoutSuccessUrl("/login"); ping请求处理程序和方法位于还包含登录处理程序的控制器中,并且没有单独的@PreAuthorize或其他可能引起此问题的注释。 问题是匿名访问被拒绝,用户被重定向到登录页面。 在调试级别进行日志记录时
  • 春季启动-Application.properties中的自定义变量(Spring boot - custom variables in Application.properties)
    问题 我有使用一个宁静的api的spring boot客户端。 不用在Java类中对REST API的IP地址进行硬编码,我可以使用application.properties中的任何键条目吗? 如果没有,我可以创建一个自定义条目吗? 谢谢 回答1 Spring Boot使用的基础架构可以以完全相同的方式在您自己的项目中使用。 您在@zmitrok答案中评论了有关“未知属性”警告的信息。 那是因为您的属性没有元数据,所以IDE对此一无所知。 我强烈建议您,如果可以的话,请不要使用@Value ,因为与Spring Boot提供的功能相比, @Value相当有限( @Value是Spring Framework功能)。 首先为您的IP创建一些POJO: @ConfigurationProperties("app.foo") public class FooProperties { /** * IP of foo service used to blah. */ private String ip = 127.0.0.1; // getter & setter } 那你有两个选择 将@Component放在FooProperties并通过在任何@Configuration类上添加@EnableConfigurationProperties来启用配置属性的处理(从Spring Boot
  • 仅使用Spring Data REST的REST API的自定义默认标头(Custom default headers for REST API only using Spring Data REST)
    问题 我有一个用例,其中我的应用程序托管REST API和Web应用程序,我们只需要向REST API添加自定义标头。 REST API通过Spring Data REST启用。 通常,我们可以使用Servlet Filter来实现此目的,但是我们需要编写将请求隔离到REST API的逻辑,并添加自定义标头。 如果Spring Data REST API允许向其生成的所有响应中添加默认标头,那就太好了。 你的想法是什么? 不要说我很懒:) 回答1 由于Spring Data REST建立在Spring MVC之上,因此最简单的方法是按照参考文档中的说明配置自定义HandlerInterceptor 。 使用Spring Data REST,最简单的方法是扩展RepositoryRestMvcConfiguration并覆盖repositoryExporterHandlerMapping ,调用父方法,然后在其上调用….setInterceptors(…) 。 回答2 对于寻求实际实施细节的人们。 拦截器 public class CustomInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request
  • 处理 Spring Boot Resource Server 中的安全异常(Handle Security exceptions in Spring Boot Resource Server)
    问题 如何让我的自定义ResponseEntityExceptionHandler或OAuth2ExceptionRenderer在纯资源服务器上处理 Spring security 引发的异常? 我们实施了一个 @ControllerAdvice @RestController public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { 所以每当资源服务器上出现错误时,我们希望它回答 { "message": "...", "type": "...", "status": 400 } 资源服务器使用 application.properties 设置: security.oauth2.resource.userInfoUri: http://localhost:9999/auth/user 对我们的身份验证服务器进行身份验证和授权请求。 但是,任何 spring 安全错误将始终绕过我们的异常处理程序 @ExceptionHandler(InvalidTokenException.class) public ResponseEntity<Map<String, Object>> handleInvalidTokenException(InvalidTokenException e) {
  • 基于用户原则的Spring Data Rest中的存储库访问控制(Repository access control in Spring Data Rest based off user princpal)
    问题 我正在尝试实现细粒度的访问控制,同时仍然利用Spring数据休息。 我正在努力保护CrudRepository以便用户只能修改或插入属于他们的数据。 我正在使用@PreAuthorize / @PostAuthorize和@PreFilter / @PostFilter来锁定对当前主体的访问。 到目前为止,我的存储库看起来像这样。 public interface MyRepository extends CrudRepository<MyObject, Integer> { @PreAuthorize("#entity.userId == principal.id") @Override <S extends MyObject> S save(S entity); @PreFilter("filterObject.userId === principal.id") @Override <S extends MyObject> Iterable<S> save(Iterable<S> entities); @PostAuthorize("returnObject.userId == principal.id") @Override MyObject findOne(Integer integer); @PostFilter("filterObject.userId ==
  • Spring 3.2 长轮询导致 SPRING_SECURITY_CONTEXT 被清除(Spring 3.2 Long polling causing SPRING_SECURITY_CONTEXT to be cleared)
    问题 我正在使用 Spring 3.2 Milestone 1 来实现长轮询服务。 然而,出于某种原因,Spring Security (3.1.2) 在第一个延迟结果过期后立即清除 SPRING_SECURITY_CONTEXT(已达到 asynctimeout 并且 tomcat 以 http.200 响应)或某些响应被发送回客户端。 使用 Spring Security 3.1.0 这仅在某些情况下发生(HTTPS 和客户端位于某些硬件防火墙后面),但使用 3.1.2 总是发生(在第一个 DefferedResult 完成之后)! 这是日志相关部分的调试输出 DEBUG: org.springframework.security.web.util.AntPathRequestMatcher - Checking match of request : '/updates/events'; against '/login*' DEBUG: org.springframework.security.web.FilterChainProxy - /updates/events?clientId=nvrs1346481959144&timestamp=0&_=1346481959526 at position 1 of 11 in additional filter chain
  • 如何在Spring Data Rest JPA实现中添加自定义方法并利用HATEOS支持?(How to add custom methods to Spring Data Rest JPA implementation and leverage HATEOS support?)
    问题 我有一个使用 JPA 进行查询实现的 Spring Data Rest Repository 控制器,我需要添加一些使用 JPA 支持的标准 queryByExample 方法无法完成的自定义查询方法。 我创建了具有必需方法的Impl类,但是无法识别它。 我看到我可以利用标准的Spring MVC控制器,但是我想要一个统一的API,基本上我真正想要的只是实现自己的自定义/ search方法。 即使使用自定义控制器,问题仍然在于不再提供HAL链接和其他相关项目。 春季人们可以花一些时间让某人记录如何做一些更高级的事情吗? 我猜有时必须实现自己的搜索方法是相当普遍的,并且花时间弄清楚如何做到这一点是值得的。 回答1 一个简单的实现可能看起来像这样: @BasePathAwareController class CustomInvocationsController implements ResourceProcessor<RepositorySearchesResource> { private final YourRepository repository; public CustomInvocationsController(YourRepository repository) { this.repository = repository; } @RequestMapping
  • 实现Spring Data存储库的自定义方法并通过REST公开它们(Implementing custom methods of Spring Data repository and exposing them through REST)
    问题 我正在尝试将自定义方法添加到我的Spring Data存储库PersonRepository ,如1.3 Data for Spring Data存储库的自定义实现中所述,并通过REST公开这些方法。 初始代码来自使用REST示例访问JPA数据,这是添加/修改的类的代码: interface PersonRepositoryCustom { List<Person> findByFistName(String name); } class PersonRepositoryImpl implements PersonRepositoryCustom, InitializingBean { @Override public void afterPropertiesSet() throws Exception { // initialization here } @Override public List<Person> findByFistName(String name) { // find the list of persons with the given firstname } } @RepositoryRestResource(collectionResourceRel = "people", path = "people") public interface
  • Ajax 调用的 Spring 安全会话超时处理(Spring security Session Timeout handling for Ajax calls)
    问题 我在使用 Spring Security 的地方创建了 webapp,并且在spring-security.xml文件中添加了 2 个自定义过滤器,如下所示。 <security:custom-filter ref="authenticationFilter" position="FORM_LOGIN_FILTER"/> <security:custom-filter ref="concurrencyFilter" position="CONCURRENT_SESSION_FILTER"/> 它适用于非 ajax 请求。 当我尝试在会话已过期时发送 AJAX 请求时,操作将登录页面作为 html 返回,作为响应加载到 div 元素中。 我已经搜索了解决方案并找到了这个链接会话超时处理 Ajax 调用,其中定义的功能返回状态代码,并且在 javascript 端使用此代码以便将用户导航到登录页面。 我的问题是: 必须在spring-security.xml文件中定义authenticationFilter 、 concurrencyFilter和ajaxTimeoutRedirectFilter 的顺序,才能正确处理请求管道? 回答1 看3)过滤器配置: 想法是在 Spring Security 过滤器链中添加上述自定义过滤器。 过滤器链中的顺序至关重要。 我们的过滤器应该在
  • Custom ExceptionTranslationFilter in spring 4 to handle REST AuthenticationException
    I have a spring MVC RESTful application secured by spring security. Client side is Angular JS. But my login and logout pages are plain jsp and I do form based login and log out. upon success full authentication, I load my secured page(it uses anlgularJS and RESTful api). I need help in handling AuthenticationException & AccessDeniedException when REST api is called. I extended ResponseEntityExceptionHandler and I am able to catch AccessDEniedException and throw a json response. I understand to handle AuthenticationException ( so I can stop 302 redirection in case of rest full request ) I need
  • 在Spring MVC 3.1中添加自定义RequestCondition(Adding custom RequestCondition's in Spring mvc 3.1)
    问题 我有一个Spring mvc(3.1.1)应用程序,我想定义超出RequestMapping可用条件的条件。 我有几件事要用于它。 首先,如果我可以为不同的用户类型显示不同的主页,那就太好了: @Controller public class HomepageController { @RequestMapping(value = "/") @CustomCondition(roles = Guest.class) public String guestHome() { /*...*/ } @RequestMapping(value = "/") @CustomCondition(roles = Admin.class) public String adminHome() { /*...*/ } } 其次,我希望该应用程序既可以充当网站,也可以充当REST服务(例如,用于移动应用程序),因此我想让该网站访问html和json操作,并仅让该服务(不同的子域)访问json操作(某种@CustomCondition(web = true) ,仅与网站网址匹配) 这可以用于我计划的两种用途吗? 我发现很少有关于自定义条件的文档,但是我确实找到了一个实现自定义条件的示例,这可能是我想要的,但是它使用了@Configuration类而不是我正在使用的XML配置
  • Spring Security用户认证和权限控制(默认实现)
    1 背景 实际应用系统中,为了安全起见,一般都必备用户认证(登录)和权限控制的功能,以识别用户是否合法,以及根据权限来控制用户是否能够执行某项操作。 Spring Security是一个安全相关的框架,能够与Spring项目无缝整合,本文主要是介绍Spring Security默认的用户认证和权限控制的使用方法和原理,但不涉及到自定义实现。 Spring Security用户认证和权限控制(自定义实现)这篇文章专门讲解用户认证和权限控制相关的自定义实现。 2 实战示例 2.1 创建工程 创建一个名为authentication-server的spring boot工程,项目结构如下图所示:说明:该spring boot工程主要是整合了Spring Security框架和Spring MVC框架。 2.2 配置说明 pom.xml配置文件如下所示: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org
  • 如何在Spring中管理在过滤器中引发的异常?(How to manage exceptions thrown in filters in Spring?)
    问题 我想使用通用方式来管理5xx错误代码,特别是当整个Spring应用程序中的db关闭时。 我想要一个漂亮的错误json而不是堆栈跟踪。 对于控制器,我为不同的异常提供了一个@ControllerAdvice类,这也捕获了db在请求中间停止的情况。 但这并不是全部。 我也碰巧有一个自定义的CorsFilter扩展了OncePerRequestFilter ,在那里,当我调用doFilter我得到了CannotGetJdbcConnectionException ,它将不会由@ControllerAdvice进行管理。 我在网上阅读了几件事,这只会让我更加困惑。 所以我有很多问题: 我是否需要实施自定义过滤器? 我找到了ExceptionTranslationFilter但是它只能处理AuthenticationException或AccessDeniedException 。 我想到实现自己的HandlerExceptionResolver ,但这使我感到怀疑,我没有要管理的任何自定义异常,必须有比这更明显的方法。 我还尝试添加一个try / catch并调用HandlerExceptionResolver的实现(应该足够好,我的异常没什么特别的),但这在响应中不返回任何内容,我得到一个状态200和一个空主体。 有什么好办法解决这个问题吗? 谢谢 回答1 所以这就是我所做的: