0

カスタムフィルターを使用してSpringセキュリティ認証を実装しようとしています。

security.xml

<?xml version="1.0" encoding="UTF-8"?>
<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" 
   xmlns:p="http://www.springframework.org/schema/p" 
   xmlns:util="http://www.springframework.org/schema/util"
   xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/security 
        http://www.springframework.org/schema/security/spring-security-3.1.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util-3.1.xsd">

    <http pattern="/resources" security="none" />

    <http auto-config="false" use-expressions="true" entry-point- ref="authenticationEntryPoint">
        <custom-filter position="BASIC_AUTH_FILTER" ref="loginFilter"/>
        <intercept-url pattern="/login" access="permitAll" />
        <intercept-url pattern="/favicon.ico" access="permitAll"/>
    </http>

    <beans:bean id="authenticationEntryPoint" class="com.my.org.MyAuthenticationEntryPoint"/>


    <beans:bean id="loginFilter"
      class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager"/>
        <beans:property name="filterProcessesUrl" value="/j_spring_security_check"/>
        <beans:property name="authenticationSuccessHandler"  >
            <beans:bean class="com.my.org.MyAuthenticationSuccessHandler"/>
    </beans:property>
        <beans:property name="authenticationFailureHandler">
            <beans:bean class="com.my.org.MyAuthenticationFailureHandler"/>
        </beans:property>
    </beans:bean>

    <authentication-manager alias="authenticationManager">
            <authentication-provider user-service-ref="customUserDetailsService">
                    <password-encoder hash="sha"/>
            </authentication-provider>
    </authentication-manager>

</beans:beans>

CustomUserDetailsS​​ervice

/**
 * A custom {@link UserDetailsService} where user information
 * is retrieved from a JPA repository
 */
@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {

private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class);

@Autowired
private UserRepository userRepository;

/**
 * Returns a populated {@link UserDetails} object. 
 * The username is first retrieved from the database and then mapped to 
 * a {@link UserDetails} object.
 */
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    try {

        logger.info("username-1-->"+username);
        com.cbr.model.User domainUser = userRepository.findByUsername(username);
        logger.info("domainUser-1-->"+domainUser.getPassword());
        logger.info("role-1-->"+domainUser.getRole().getRole());

        boolean enabled = true;
        boolean accountNonExpired = true;
        boolean credentialsNonExpired = true;
        boolean accountNonLocked = true;

        return new User(
                domainUser.getUsername(), 
                domainUser.getPassword().toLowerCase(),
                enabled,
                accountNonExpired,
                credentialsNonExpired,
                accountNonLocked,
                getAuthorities(domainUser.getRole().getRole()));

    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

/**
 * Retrieves a collection of {@link GrantedAuthority} based on a numerical role
 * @param role the numerical role
 * @return a collection of {@link GrantedAuthority
 */
public Collection<? extends GrantedAuthority> getAuthorities(Integer role) {
    List<GrantedAuthority> authList = getGrantedAuthorities(getRoles(role));
    return authList;
}

/**
 * Converts a numerical role to an equivalent list of roles
 * @param role the numerical role
 * @return list of roles as as a list of {@link String}
 */
public List<String> getRoles(Integer role) {
    List<String> roles = new ArrayList<String>();

    if (role.intValue() == 1) {
        roles.add("ROLE_USER");
        roles.add("ROLE_ADMIN");

    } else if (role.intValue() == 2) {
        roles.add("ROLE_USER");
    }

    return roles;
}

/**
 * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
 * @param roles {@link String} of roles
 * @return list of granted authorities
 */
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
    for (String role : roles) {
        authorities.add(new SimpleGrantedAuthority(role));
    }
    return authorities;
}

}

MyAuthenticationEntryPoint

public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {

    private Log log = LogFactory.getLog(MyAuthenticationEntryPoint.class);

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

        log.info("point-1");

        response.sendError(HttpServletResponse.SC_FORBIDDEN);
    }
}

MyAuthenticationSuccessHandler

public class MyAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {

    private Log log = LogFactory.getLog(MyAuthenticationSuccessHandler.class);

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,Authentication authentication) throws IOException, ServletException {
        // This is actually not an error, but an OK message. It is sent to avoid redirects.
        log.info("point-2");
        response.sendError(HttpServletResponse.SC_OK);
    }
}

MyAuthenticationFailureHandler

public class MyAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    private Log log = LogFactory.getLog(MyAuthenticationFailureHandler.class);

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException exception) throws IOException, ServletException {
        log.info("point-3");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());
    }
}

ログインしようとすると、CustomUserDetailsS​​erviceが表示され、データベースからユーザーの詳細を正常に取得できます。

ただし、資格情報が正しいかどうかに関係なく、常にauthenticationFailureHandlerにアクセスします。(INFO : com.my.org.MyAuthenticationFailureHandler - point-3

誰かがこれについて私を助けてくれますか?ありがとう

4

1 に答える 1

3

shaパスワードエンコーディング( )を使用するように認証プロバイダーを構成しました<password-encoder hash="sha"/>。これは、着信ログイン要求で提示されたパスワードを共有エンコードし、そのエンコードされた値をUserDetailsオブジェクトに保存されているパスワードと比較することを意味します(結果として共有されると予想されます)。同様にエンコードされます)。UserDetailsでオブジェクトを作成するCustomUserDetailsService.loadUserByUsername()と、ユーザーはリポジトリからロードされ、パスワードを。で変換しますtoLowerCase()。さて、一体なぜあなたはそれをするのですか?その値は、shaでエンコードされたパスワードであると想定されています。パスワードのハッシュを変換することにより、ユーザーが元のパスワードでログインできないことを保証します。ただし、パスワードをプレーンテキストで保存している場合でも(この場合、password-encoder構成を削除する必要があります)、なぜパスワードを小文字にするのでしょうか。UserDetails?これを行い、ユーザーが自分のパスワードを「シークレット」に設定すると、後で「シークレット」でしか認証できなくなります。

于 2013-03-11T22:38:12.093 に答える