@SuppressWarnings({"ThrowableInstanceNeverThrown"}) private void useAnonymousIfPossible( HttpServletRequest request, HttpServletResponse response, FilterChain chain, SecurityContext securityContext) throws IOException, ServletException { boolean anonAccessEnabled = context.getAuthorizationService().isAnonAccessEnabled(); if (anonAccessEnabled || authInterceptors.accept(request)) { log.debug("Using anonymous"); Authentication authentication = getNonUiCachedAuthentication(request); if (authentication == null) { log.debug("Creating the Anonymous token"); final UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(UserInfo.ANONYMOUS, ""); AuthenticationDetailsSource ads = new HttpAuthenticationDetailsSource(); //noinspection unchecked authRequest.setDetails(ads.buildDetails(request)); // explicitly ask for the default spring authentication manager by name (we have another one // which // is only used by the basic authentication filter) AuthenticationManager authenticationManager = context.beanForType("authenticationManager", AuthenticationManager.class); authentication = authenticationManager.authenticate(authRequest); if (authentication != null && authentication.isAuthenticated() && !RequestUtils.isUiRequest(request)) { AuthCacheKey authCacheKey = new AuthCacheKey(authFilter.getCacheKey(request), request.getRemoteAddr()); nonUiAuthCache.put(authCacheKey, authentication); log.debug("Added anonymous authentication {} to cache", authentication); } } else { log.debug("Using cached anonymous authentication"); } useAuthentication(request, response, chain, authentication, securityContext); } else { if (authFilter.acceptEntry(request)) { log.debug("Sending request requiring authentication"); authFilter.commence( request, response, new InsufficientAuthenticationException("Authentication is required")); } else { log.debug("No filter or entry just chain"); chain.doFilter(request, response); } } }
private Authentication getNonUiCachedAuthentication(HttpServletRequest request) { // return cached authentication only if this is a non ui request (this guards the case when user // accessed // Artifactory both from external tool and from the ui) AuthCacheKey authCacheKey = new AuthCacheKey(authFilter.getCacheKey(request), request.getRemoteAddr()); return RequestUtils.isUiRequest(request) ? null : nonUiAuthCache.get(authCacheKey); }
private void authenticateAndExecute( HttpServletRequest request, HttpServletResponse response, FilterChain chain, SecurityContext securityContext) throws IOException, ServletException { // Try to see if authentication in cache based on the hashed header and client ip Authentication authentication = getNonUiCachedAuthentication(request); if (authentication != null && authentication.isAuthenticated() && !reAuthenticationRequired(request, authentication)) { log.debug("Header authentication {} found in cache.", authentication); useAuthentication(request, response, chain, authentication, securityContext); // Add to user change cache the login state addToUserChange(authentication); return; } try { authFilter.doFilter(request, response, chain); } finally { Authentication newAuthentication = securityContext.getAuthentication(); if (newAuthentication != null && newAuthentication.isAuthenticated()) { // Add to user change cache the login state addToUserChange(newAuthentication); // Save authentication like in Wicket Session (if session exists) if (RequestUtils.setAuthentication(request, newAuthentication, false)) { log.debug("Added authentication {} in Http session.", newAuthentication); } else { // If it did not work use the header cache // An authorization cache key with no header can only be used for Anonymous authentication AuthCacheKey authCacheKey = new AuthCacheKey(authFilter.getCacheKey(request), request.getRemoteAddr()); String username = newAuthentication.getName(); if ((UserInfo.ANONYMOUS.equals(username) && authCacheKey.hasEmptyHeader()) || (!UserInfo.ANONYMOUS.equals(username) && !authCacheKey.hasEmptyHeader())) { nonUiAuthCache.put(authCacheKey, newAuthentication); userChangedCache.get(username).addAuthCacheKey(authCacheKey); log.debug("Added authentication {} in cache.", newAuthentication); } } } securityContext.setAuthentication(null); } }
@Override public void initLater(FilterConfig filterConfig) throws ServletException { ServletContext servletContext = filterConfig.getServletContext(); this.context = RequestUtils.getArtifactoryContext(servletContext); ArtifactoryAuthenticationFilterChain filterChain = new ArtifactoryAuthenticationFilterChain(); // Add all the authentication filters // TODO: [by yl] Support ordering... filterChain.addFilters(context.beansForType(ArtifactoryAuthenticationFilter.class).values()); authFilter = filterChain; initCaches(filterConfig); authFilter.init(filterConfig); authInterceptors = new AnonymousAuthenticationInterceptors(); authInterceptors.addInterceptors( context.beansForType(AnonymousAuthenticationInterceptor.class).values()); }
private boolean reAuthenticationRequired( HttpServletRequest request, Authentication authentication) { if (authentication == null || !authentication.isAuthenticated()) { // Not authenticated so not required to redo ;-) return false; } // If user changed force re-auth String username = authentication.getName(); AuthenticationCache authenticationCache = userChangedCache.get(username); if (authenticationCache != null && authenticationCache.isChanged(authentication)) { authenticationCache.loggedOut(authentication); return true; } return authFilter.requiresReAuthentication(request, authentication); }
@Override public void destroy() { // May not be inited yet if (authFilter != null) { authFilter.destroy(); } if (nonUiAuthCache != null) { nonUiAuthCache.clear(); nonUiAuthCache = null; } if (userChangedCache != null) { userChangedCache.clear(); userChangedCache = null; } }
private void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { final String servletPath = RequestUtils.getServletPathFromRequest(request); // add no cache header to web app request RequestUtils.addNoCacheToWebAppRequest(servletPath, response); String method = request.getMethod(); if ((servletPath == null || "/".equals(servletPath) || servletPath.length() == 0) && "get".equalsIgnoreCase(method)) { // We were called with an empty path - redirect to the app main page response.sendRedirect(HttpUtils.ANGULAR_WEBAPP + "/"); return; } // Reuse the authentication if it exists Authentication authentication = RequestUtils.getAuthentication(request); boolean isAuthenticated = authentication != null && authentication.isAuthenticated(); // Make sure this is called only once boolean reAuthRequired = reAuthenticationRequired(request, authentication); if (reAuthRequired) { /** * A re-authentication is required but we might still have data that needs to be invalidated * (like the Wicket session) */ Map<String, LogoutHandler> logoutHandlers = ContextHelper.get().beansForType(LogoutHandler.class); for (LogoutHandler logoutHandler : logoutHandlers.values()) { logoutHandler.logout(request, response, authentication); } } boolean authenticationRequired = !isAuthenticated || reAuthRequired; SecurityContext securityContext = SecurityContextHolder.getContext(); if (authenticationRequired) { if (authFilter.acceptFilter(request)) { authenticateAndExecute(request, response, chain, securityContext); } else { useAnonymousIfPossible(request, response, chain, securityContext); } } else { log.debug("Using authentication {} from Http session.", authentication); useAuthentication(request, response, chain, authentication, securityContext); } }