数据库停止时,Spring安全性返回401

时间:2015-10-16 08:15:33

标签: java spring spring-security

我已使用自定义身份验证管理器配置了spring基本身份验证。我的认证管理器将访问数据库以获取用户信息当数据库停止并且应用程序尝试验证用户时,我的应用程序返回401(未授权)。但我的预期行为是在这种情况下返回500(内部服务器错误)。以下是我配置弹簧安全性的方法。

<context:component-scan base-package="com.test.security" />

	<sec:http use-expressions="true">

		<sec:intercept-url pattern="/**" access="hasAnyRole('Admin','Data Operator','Data Collector')" />
		<sec:http-basic />
		
	</sec:http>

	<sec:authentication-manager alias="authenticationManager">
		<sec:authentication-provider
			user-service-ref="myAuthenticationProvider">
			<sec:password-encoder ref="encoder" />
		</sec:authentication-provider>
	</sec:authentication-manager>

	<bean id="myAuthenticationProvider"
		class="com.test.security.MyUserDetailsService" />


	<bean id="encoder"
		 class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
	</bean>

以下是身份验证提供程序

的实现
package com.test.security;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.test.business.objects.Adminrole;
import com.test.business.objects.Adminuser;
import com.test.business.repository.AdminroleRepository;
import com.test.repository.AdminuserRepository;

@Service
public class MyUserDetailsService implements UserDetailsService{

    @Autowired
    private AdminuserRepository adminuserRepository;

    @Autowired
    private AdminroleRepository adminroleRepository;






    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{



        //find admin user by user name
        List<Adminuser> adminUsers = adminuserRepository.findByUsername(username);
        Adminuser adminUser = adminUsers.get(0);

        //find admin roles by user
        List<Adminrole> adminRoles = adminroleRepository.getAdminRolesByUserId(adminUser.getUserid());

        //create user details object
        MyUserDetails userdetails = new MyUserDetails(adminUser, adminRoles);
        return userdetails;

    }

}

3 个答案:

答案 0 :(得分:0)

看看this javadoc。它显示UsernameNotFoundException是AuthenticationException。我的猜测是,您在访问数据库并将其转换为UsernameNotFoundException时捕获异常。看看您的数据库代码,这可能是问题所在。

答案 1 :(得分:0)

从我的角度来看,这是弹性服务的正确行为。如果只是身份验证被破坏,为什么整个服务器都会中断?即使没有可访问的用户数据库,也可能存在服务器的公共可用资源,无论如何都应该可用。例如,即使用户登录并获得了令牌,只要令牌有效,为什么他不应该访问受保护的资源? Spring Security团队在这方面做得很好,就像他们一样。你不应该改变行为。

答案 2 :(得分:0)

我找到了解决方案。

&#13;
&#13;
<context:component-scan base-package="com.test.security" />

	<sec:http use-expressions="true">

		<sec:intercept-url pattern="/**" access="hasAnyRole('Admin','Data Operator','Data Collector')" />
		<sec:http-basic  entry-point-ref="basicAuthenticationEntryPoint"/>
		
	</sec:http>

	<sec:authentication-manager alias="authenticationManager">
		<sec:authentication-provider
			user-service-ref="myAuthenticationProvider">
			<sec:password-encoder ref="encoder" />
		</sec:authentication-provider>
	</sec:authentication-manager>

	<bean id="myAuthenticationProvider"
		class="com.test.security.MyUserDetailsService" />

	<bean id="encoder"
		 class="org.springframework.security.authentication.encoding.Md5PasswordEncoder">
	</bean>
<bean id="basicAuthenticationEntryPoint"
	 class="com.test.MyAuthenticationEntryPoint"/>
&#13;
&#13;
&#13;

package com.test.security;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionException;

@Component
public class MyAuthenticationEntryPoint  extends BasicAuthenticationEntryPoint{
     @Override
        public void commence
          (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
          throws IOException, ServletException {

            if (authEx.getCause() instanceof TransactionException){
                 response.addHeader("Internal Server Error", "Basic realm='" + getRealmName() + "'");
                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }else{
                response.addHeader("Authenticate-Faliure", "Basic realm='" + getRealmName() + "'");
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }

        @Override
        public void afterPropertiesSet() throws Exception {
            setRealmName("test");
            super.afterPropertiesSet();
        }
}