1

WebアプリケーションにSpringセキュリティを使用しようとしています。ログイン機能を作成しようとしています。これにより、ユーザーは自分のWebサイトの保護されたページにログインできます。これまで私はSpringsecurity独自のものを使用しており、認証にメモリ内のデータストアを使用していました(まだ学習中であるため、主にそれが機能するかどうかをテストするために)。

さまざまなユーザーを保存しているデータベースを使用しようとすると、問題が発生します。ログインしようとすると、Spring Securityは、ログインする代わりに、「authentication-failure-url」にリダイレクトします。

カスタムUserDetailsクラスを作成しました

package dk.chakula.web.security;

import dk.chakula.web.domain.User;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
/**
 *
 * @author Martin Rohwedder
 * @since 20-02-2013
 * @version 1.0
 */
public class ChakulaUserDetails implements UserDetails {

    private User user;
    private List<? extends GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

    public ChakulaUserDetails(User user, List<? extends GrantedAuthority> authorities)         {
        this.user = user;
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return this.user.getPassword();
    }

    @Override
    public String getUsername() {
        return this.user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

また、「authentication-provider」が参照しているカスタムUserDetailsS​​erviceを作成しました。そのクラスは次のようになります。

package dk.chakula.web.security;

import dk.chakula.web.domain.User;
import dk.chakula.web.service.UserService;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Component;
/**
 *
 * @author Martin Rohwedder
 * @since 20-02-2013
 * @version 1.0
 */
@Component("chakulaUserDetailsService")
public class ChakulaUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isBlank(username)) {
            throw new UsernameNotFoundException("Username was empty");
        }

        User user = userService.getUserByUsername(username);

        if (user == null) {
            throw new UsernameNotFoundException("User with username '" + username + "' was not found");
        }

        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        grantedAuthorities.add(new SimpleGrantedAuthority(user.getUserRole()));

        return new ChakulaUserDetails(user, grantedAuthorities);
    }

}

私の完全な春のセキュリティコンテキストは次のようになります

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:security="http://www.springframework.org/schema/security"
       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">

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

        <!-- Form Login Filter -->
        <security:form-login login-page="/login" default-target-url="/app/start" authentication-failure-url="/login?authenticationNok=1" username-parameter="username" password-parameter="password" always-use-default-target="true" />

        <!-- Logout Filter -->
        <security:logout logout-success-url="/home?logoutOk=1" logout-url="/logout" invalidate-session="true" />

        <!-- Intercept Url filters -->
        <security:intercept-url pattern="/" access="permitAll" />
        <security:intercept-url pattern="/home" access="permitAll" />
        <security:intercept-url pattern="/about" access="permitAll" />
        <security:intercept-url pattern="/login" access="permitAll" />
        <security:intercept-url pattern="/resources/**" access="permitAll" />

        <security:intercept-url pattern="/app/**" access="fullyAuthenticated" />

    </security:http>

    <bean id="chakulaUserDetailsService" class="dk.chakula.web.security.ChakulaUserDetailsService" />

    <security:authentication-manager>
        <security:authentication-provider user-service-ref="chakulaUserDetailsService">
            <security:password-encoder hash="sha-256">
                <security:salt-source user-property="username" />
            </security:password-encoder>
            <!--
            <security:user-service>
                <security:user name="test" password="e9233bd61e14137a7e28f92c50ce279215e774a1772d1e9dad5f275b9cc8177c" authorities="ROLE_CUSTOMER" />
            </security:user-service>
            -->
        </security:authentication-provider>
    </security:authentication-manager>

</beans>

GITHUBのChakulaプロジェクトですべてのソースコードを確認できます。これが必要な場合は、https://github.com/martin-rohwedder/chakula

4

1 に答える 1

0

これはすべて、Dao実装クラスの失敗のように見えました。AuthenticationExceptionのメッセージを表示したときに、次のように表示されたためです。プロパティを解決できませんでした:USERNAME of:dk.chakula.web.domain.User [from dk.chakula .web.domain.User uここで、u.USERNAME =:USERNAME]

私がしなければならなかったのは、大文字以外の文字でu.USERNAMEを書くことだけでした。

代わりに、セキュリティコンテキストxmlファイルのform-loginタグauthentication-failure-url属性を次の値に書き直しました。

 <security:form-login login-page="/login" default-target-url="/app/start" authentication-failure-url="/login/failure" username-parameter="username" password-parameter="password" always-use-default-target="true" />

その後、AuthenticationControllerで、失敗ビューをレンダリングする新しいメソッドを作成し、AuthenticationExceptionメッセージをモデルとしてビューに追加しました。

@RequestMapping(value = {"/login/failure"}, method = RequestMethod.GET)
public ModelAndView renderLoginFailureView(HttpServletRequest request) {
    ModelAndView mav = new ModelAndView("login");
    AuthenticationException authEx = (AuthenticationException) request.getSession().getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);

    mav.addObject("authEx", authEx.getMessage());
    return mav;
}

次回は、stackoverflowに突入する前に、すべての例外メッセージを表示することを知っています。今では他の人も将来私の答えに利益をもたらすかもしれませんが。

ここで私を助けてくれたArunPJohnyに感謝します。

于 2013-02-21T12:16:44.057 に答える