【问题标题】:spring security custom authentication not working春季安全自定义身份验证不起作用
【发布时间】:2017-08-29 13:47:22
【问题描述】:

我正在运行基于 spring security 4.2 版、spring mvc 4.2 版的 Web 应用程序。我想运行 customAuthenticationProvidercustomAuthenticationSuccessHandler,但 customAuthenticationProvider 类没有被调用并且请求只会发送到 authentication-failure-url

pom.xml

          <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>4.2.0.RELEASE</version>
            </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

        <!-- Spring Security Jars starts-->
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.2.0.RELEASE</version>
        </dependency>
        <!-- Spring Security Jars ends-->

application-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">

    <http pattern="/resources/css/**" security="none"/>
    <http pattern="/resources/img/**" security="none"/>
    <http pattern="/resources/js/**" security="none"/>



    <http auto-config="false" use-expressions="true"> 
<!--    <intercept-url pattern="/onemoretime/*" access="hasRole('ROLE_ADMIN')"/>-->
        <intercept-url pattern="/admin/*" access="permitAll"/>
        <intercept-url pattern="/vendor/*" access="permitAll"/>
        <form-login login-page="/login"         
                    username-parameter="username"
                    password-parameter="password"
                    authentication-success-handler-ref="customAuthenticationSuccessHandler"
                    authentication-failure-url="/accessdenied"
                    />

        <!-- <logout logout-success-url="/login"/>       -->    
         <csrf />
    </http>

    <authentication-manager alias="authenticationProvider">
        <authentication-provider ref="myAuthenticationProvider"/> 

    </authentication-manager>

    <!-- Bean implementing AuthenticationProvider of Spring Security -->
    <beans:bean id="myAuthenticationProvider" class="com.opstree.vendorportal.authentication.CustomAuthenticationProvider"/>

    <beans:bean id="customAuthenticationSuccessHandler" class="com.opstree.vendorportal.authentication.CustomAuthenticationSuccess"/>

</beans:beans>

web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:/service.xml /WEB-INF/application-security.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

loginpage.jsp

    <form action="${pageContext.request.contextPath}/login" method="post">
        <table>
            <tr>
                <td>UserName</td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td>Password</td>
                <td><input type="password" name="password"> </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <div style="color:red" class="servererror">
                        <c:if test="${not empty userobject}">
                            <b><c:out value="${userobject.message}"></c:out></b>
                        </c:if>
                    </div>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <input type="submit" value="Login">
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b><a href="forgotpassword">ForgotPassword</a></b>
                </td>
            </tr>
            <tr>
                <td align="center" colspan="2">
                    <b>Click here to <a href="registerVendor">Register</a></b>
                </td>
            </tr>
        </table>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
    </form>

customAuthenticationProvider

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDBOperationsImpl userDAO;

    private Logger logger = Logger.getLogger(getClass());

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        System.out.println("Spring Security: Entered");
        UsernamePasswordAuthenticationToken  authenticationToken = (UsernamePasswordAuthenticationToken) authentication;
        String username = authenticationToken.getName();
        //String password = (String) authenticationToken.getCredentials();

        UserBean userBean = null;

        try {
            userBean =  userDAO.getUserDetails(username);
        } catch (Exception e) {
            logger.error(e.getCause().getMessage());
        }

        if(userBean == null){
            throw new BadCredentialsException("Invalid Credentials");
        }
        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

        Authentication auth = new UsernamePasswordAuthenticationToken(userBean, userBean.getPassword(), authorities);

        System.out.println("Exit");
        return auth;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(getClass());
    }

customAuthenticationSuccess

public class CustomAuthenticationSuccess implements AuthenticationSuccessHandler {

    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
            throws IOException, ServletException {
        System.out.println("Entered Authentication Successful Method");
        boolean isUser = false;
        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
        String targetUrl = null;
        for(GrantedAuthority currentAuth : authorities){
            if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
                isUser = true;
                break;
            }
            else {
                throw new IllegalStateException();
            }
        }

        if(isUser){
            targetUrl = "/vendor";
        }
        System.out.println("Entered Authentication Successful Method");
        redirectStrategy.sendRedirect(request, response, targetUrl);
    }
}

【问题讨论】:

    标签: java spring spring-mvc spring-security


    【解决方案1】:

    我认为发生的事情是您的AuthenticationProvider 中的supports(Class&lt;?&gt; authentication) 方法没有正确实现。

    您正在根据您的 CustomAuthenticationProvider getClass() 方法检查收到的 Authentication 类,因此它总是会返回 false,AuthenticationManager 不会将您的提供者识别为接收到的 UsernamePasswordAuthenticationToken 的合适提供者。

    您可以检查 github 中的 org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider 代码,您可以在其中看到在 UsernamePasswordAuthenticationToken 支持提供程序中此方法的正确实现应该是这样的:

    public boolean supports(Class<?> authentication) {
        return (UsernamePasswordAuthenticationToken.class
                .isAssignableFrom(authentication));
    }
    

    我猜实际发生的情况是AuthenticationManager 找不到UsernamePasswordAuthenticationToken 支持提供程序,因此无法执行身份验证,未经授权的Authentication 正在到达UsernamePasswordAuthenticationFilter,这最终无关重定向到authentication-failure-url

    也要小心你的AuthenticationSuccessHandler,你检查GranthedAuthorities 的方式可能会以IllegalStateException 结尾,以防评估的第一个GranthedAuthority 不是ROLE_USER 一个:

            for(GrantedAuthority currentAuth : authorities){
                if(currentAuth.getAuthority().equalsIgnoreCase("ROLE_USER")){
                    isUser = true;
                    break;
                }
                else {
                    throw new IllegalStateException();
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2015-12-16
      • 1970-01-01
      • 2013-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-22
      • 2015-07-30
      • 2016-08-20
      相关资源
      最近更新 更多