spring security 用户名密码错误返回401页面

因为要在登陆的时候增加企业编号验证,自己定义了DisUsernamePasswordAuthenticationFilter类并继承AbstractAuthenticationProcessingFilter这个类,但是运行后发现只要用户名密码错误或者没有权限等其他错误都返回401 -Authentication Failed,如下图:

后经过排查发现,在重写AbstractAuthenticationProcessingFilter类时没有传入登录失败跳转的路径failureUrl.找到问题后我在AbstractAuthenticationProcessingFilter发现该类定义了AuthenticationSuccessHandler和AuthenticationFailureHandler,所以我们可以在application-security.xml中定义一下代码:

<beans:bean id="simpleUrlAuthenticationFailureHandler"  
        class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFai            lureHandler">  
        <!-- 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sen            dRedirect -->  
        <beans:property name="defaultFailureUrl" value="/login.jsp?auth-failure=true"></b                eans:property>  
</beans:bean>

并在自定义的DisUsernamePasswordAuthenticationFilter类中引入

  <!-- 登录处理Filter  -->  
    <beans:bean id="loginProcessFilter" class="com.fpi.safety.common.security.DisUsername        PasswordAuthenticationFilter">  
        <beans:property name="companyCode" value="companyCode" />  
        <beans:property name="usernameParameter" value="username" />    
        <beans:property name="passwordParameter" value="password" />  
        <!-- 登陆失败处理类 -->
        <beans:property name="simpleUrlAuthenticationFailureHandler" ref="simpleUrlAuthen            ticationFailureHandler" /> 
        <beans:property name="authenticationSuccessHandler" ref="appSessionSuccessHandler        " />  
        <beans:property name="authenticationManager" ref="disuserAuthManager" /> 
    </beans:bean>

DisUsernamePasswordAuthenticationFilter.java

public class DisUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter  {

    public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
    public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
    public static final String SPRING_SECURITY_FORM_COMPANY_CODE_KEY = "company_code";
    public static final String USERNAME_LOGINID_SPLIT = "-"; 
   
    /**
     * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler}
     */
    @Deprecated
    public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";

    private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
    private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
    private String companyCode = SPRING_SECURITY_FORM_COMPANY_CODE_KEY;
    private SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler;
    
    private boolean postOnly = true;

    //~ Constructors ===================================================================================================

    public DisUsernamePasswordAuthenticationFilter() {
        super("/j_spring_security_check");
    }

    //~ Methods ========================================================================================================

    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        String username = obtainUsername(request);
        String password = obtainPassword(request);
        String companyCode = obtainCompanyCode(request);
        
        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }
        
        if(companyCode == null || companyCode.equals("")){
        	companyCode = "null";
        }
       
        username = username.trim();
        companyCode =  companyCode.trim();
        
        username = username+USERNAME_LOGINID_SPLIT+companyCode;
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);

        return this.getAuthenticationManager().authenticate(authRequest);
    }

    
    protected String obtainCompanyCode(HttpServletRequest request) {
        return request.getParameter(companyCode);
    }
    /**
     * Enables subclasses to override the composition of the password, such as by including additional values
     * and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the
     * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The
     * <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p>
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the password that will be presented in the <code>Authentication</code> request token to the
     *         <code>AuthenticationManager</code>
     */
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(passwordParameter);
    }

    /**
     * Enables subclasses to override the composition of the username, such as by including additional values
     * and a separator.
     *
     * @param request so that request attributes can be retrieved
     *
     * @return the username that will be presented in the <code>Authentication</code> request token to the
     *         <code>AuthenticationManager</code>
     */
    protected String obtainUsername(HttpServletRequest request) {
        return request.getParameter(usernameParameter);
    }

    /**
     * Provided so that subclasses may configure what is put into the authentication request‘s details
     * property.
     *
     * @param request that an authentication request is being created for
     * @param authRequest the authentication request object that should have its details set
     */
    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    /**
     * Sets the parameter name which will be used to obtain the username from the login request.
     *
     * @param usernameParameter the parameter name. Defaults to "j_username".
     */
    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.usernameParameter = usernameParameter;
    }

    /**
     * Sets the parameter name which will be used to obtain the password from the login request..
     *
     * @param passwordParameter the parameter name. Defaults to "j_password".
     */
    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.passwordParameter = passwordParameter;
    }
    
    
    @Override
    public void afterPropertiesSet() {
    	super.afterPropertiesSet();
    	/* 
         *该处理器实现了 AuthenticationFailureHandler 
         *用于处理登录失败后,跳转的界面 
         */  
    	this.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler);
    }
    
    
    /**
     * Defines whether only HTTP POST requests will be allowed by this filter.
     * If set to true, and an authentication request is received which is not a POST request, an exception will
     * be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method
     * will be called as if handling a failed authentication.
     * <p>
     * Defaults to <tt>true</tt> but may be overridden by subclasses.
     */
    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getUsernameParameter() {
        return usernameParameter;
    }

    public final String getPasswordParameter() {
        return passwordParameter;
    }

	public String getCompanyCode() {
		return companyCode;
	}

	public void setCompanyCode(String companyCode) {
		this.companyCode = companyCode;
	}

	public SimpleUrlAuthenticationFailureHandler getSimpleUrlAuthenticationFailureHandler() {
		return simpleUrlAuthenticationFailureHandler;
	}

	public void setSimpleUrlAuthenticationFailureHandler(
			SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler) {
		this.simpleUrlAuthenticationFailureHandler = simpleUrlAuthenticationFailureHandler;
	}
    
    
}

这样就能使登陆错误成功返回登陆页面,问题得以解决。

时间: 2024-10-24 15:57:37

spring security 用户名密码错误返回401页面的相关文章

Spring Security PasswordEncoder 密码校验和密码加密

Spring Security PasswordEncoder 密码校验和密码加密流程 PasswordEncoder 使用 首先我们先来看看一个创建密码编码器工厂方法 org/springframework/security/crypto/factory/PasswordEncoderFactories.java public static PasswordEncoder createDelegatingPasswordEncoder() { String encodingId = "bcry

win7访问远程共享文件总是提示用户名密码错误

局域网内共享了个文件,在别的同事电脑输入用户名密码后均可正常访问,但是我的pc访问时却始终是提示用户名密码错误,记得这个共享文件都建立很久了,以前我的pc机貌似也可以正常访问它,这问题让我很纳闷.后来搜了很久,在网上找到了答案.说是win7在安全方面比较重视,但也由此导致了一些日常操作的不方便,比如我们在某台电脑上共享了一个文件夹,然后想在别的电脑上访问,使用xp系统时只要搜索到相应的共享文件夹然后输入正确的帐号和密码就可以使用,而同样的帐号和密码win7却总是提示帐号密码错误. 具体解决方案如

安装腾讯通 rtx 老是提示用户名密码错误

在自己机器上安装rtx服务器和客户端 测试 系统是win7  64 旗舰版 从企鹅上下载的2013 rtx 服务端和客户端 账户用的是普通用户user 在安装rtx服务端时候 会在桌面上出现一个rtxinstall.txt的文件 里面提示大量的 指定服务未安装 在qq群里问了人  有人说是因为 没有权限 改用administrator账户 安装就没问题了 给企鹅打电话一直没人接 耗费了我好久的时间 这是我第一次记录工作笔记,我以后会每天记录自己在工作和学习过程中遇到的问题和做过的项目,写给未来的

vmware vcenter orchestrator configuration提示“用户名密码错误或登录失败超过次数被锁定”

首次登录,使用默认用户密码登录vmware/vmware vmware vcenter orchestrator configuration提示"用户名密码错误或登录失败超过次数被锁定".记得之前没有修改过密码,但是就是登录不了,只能通过重置找回密码了. Windows:在vcenter服务器上找到vmware安装目录下的passwd文件 Linux:/var/lib/vco/configuration/conf/passwd.properties Windows:使用文本编辑器打开p

win7访问局域网总提示用户名密码错误解决方案

win7访问局域网总提示用户名密码错误解决方案 1.点击开始-在搜索栏输入:secpol.msc(或者直接按下win+r键,输入secpol.msc),打开本地安全策略. 2.找到“安全设置”的“本地策略”的“安全选项” 3.在右边一栏找到“网络安全:LAN管理器身份验证级别”,双击进入 4.在默认状态选项下,英文版应该为"no defined",中文版为空.下拉那个默认选项,选择“仅发送NTLM响应” 5.确认

Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息

spring boot以其众多友谊的特性,如零配置.微服务等,吸引了很多的粉丝.而其与Spring Security安全框架的无缝结合,使其具备的安全的特性.在此基础上使用Thymeleaf模板引擎进行渲染,静动态结合,让页面开发更加简单.直观. 通过表单提交登录的用户名和密码是登录接口比较常见的一种设计.在初学的过程中,我也不例外的采用个这种方式.表单设计见下图. 登录成功,完成正常的主页面跳转,这个不存在问题.存在问题的是,登录失败了该咋办呢?我就在考虑,由于thymeleaf的局部刷新操作

shiro的权限控制应用,集成spring项目,密码错误次数过多短时间锁定

以前对shiro都是一知半解,最近系统学了一遍shiro并集成到了在做的项目中. 下面就详细向大家描述一下shiro的用法. 首先是对spring的配置文件,如下: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3

Spring Security OAuth2 授权失败(401 问题整理

Spring Cloud架构中采用Spring Security OAuth2作为权限控制,关于OAuth2详细介绍可以参考 http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 项目中采用OAuth2四种模式中的两种,Password模式和Client模式, Password模式用于控制用户的登录,Client模式用于控制后端服务相互调用. 权限架构调整后在近期发现一些问题,由于网上资料不多,只能单步调试方式看源码 (其实带着问题看源码是最

Linux修改用户名密码后,Weblogic启动报用户名密码错误

weblogic.security.SecurityInitializationException: Authentication denied: Boot identity not valid; The user name and/or password from the boot identity file (boot.properties) is not valid. The boot identity may have been changed since the boot identi