6

タイトルが示すように、外部アプリケーションからユーザー認証情報を受け取る Web アプリケーションを開発しています。アプリのスプリング コントローラーがユーザー情報を取得し、それをセッションに保存します。Spring Security 内でこのユーザーを認証し、彼のロールを使用して、次のような URL へのアクセスを許可/拒否したい

<intercept-url pattern="/myprotectedpage*" access="hasRole('rightrole')" />

PRE_AUTH_FILTER と UserDetailsS​​ervice について話しているチュートリアルをいくつか読みましたが、要点がわかりません。Spring Security のアプリケーション ライフサイクルとは? どのクラスが関係していますか? 完全に機能するサンプルが必要です。

4

3 に答える 3

1

同じためにそこにたくさんのtutsがあります、ただ適切にグーグルする必要があります。

とにかく、私がこれまでに見つけた最高のもの(ほとんどすべての春の房)はKramsであり、これが基本的な春のセキュリティのためのものです。

http://krams915.blogspot.com/2010/12/spring-security-mvc-integration_18.html

UserDetailServiceを実装するためのリンクは次のとおりです

http://krams915.blogspot.in/2012/01/spring-security-31-implement_5023.html

他のいくつかは:

  1. 例による春
  2. MKヤング
  3. そしてSpringSourceサイト自体

編集

これは私自身のアプリケーションが認証を行う方法です(私は外部認証を使用しないことに注意してください。DBから詳細を取得するだけですが、それほど問題にはならないはずです)。

私のsecurity-context.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"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <global-method-security pre-post-annotations="enabled" jsr250-annotations="enabled" secured-annotations="enabled">
    </global-method-security>

    <http use-expressions="true">
        <intercept-url pattern="/favicon.ico" access="permitAll" />
        <intercept-url pattern="/static/**" access="permitAll"/>
        <intercept-url pattern="/login.jsp*" access="permitAll"/> 
        <intercept-url pattern="/Admin/**" access="hasAnyRole('ROLE_SUPER_USER')"/>
        <intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_SUPER_USER','ROLE_ADMIN'"/>
        <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" />
        <http-basic/>
        <logout logout-success-url="/login.jsp"/>
        <remember-me user-service-ref="loginService" /
     </http>

    <authentication-manager>
        <authentication-provider user-service-ref="loginService">
         <password-encoder hash="md5"/>
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="loginService" class="com.indyaah.service.LoginService">
    </beans:bean>
    <beans:bean id="authService" class="com.indyaah.service.AuthService" />
</beans:beans>

loginServiceご覧のとおり、クラスのBeanである認証プロバイダーとして名前が付けられたBeanを指定しましたcom.indyaah.service.LoginService

同じコードは次のとおりです 。Pl注不要なコードを切り捨てました

package com.indyaah.service;
..
@Service
public class LoginService implements UserDetailsService {

....

    /**
     * Implementation for custom spring security UserDetailsService
     */
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
        logger.debug("Inside get member by username");
        if (userName != null) {
            Member memberVO = memberMapper.getMemberByUsername(userName);
            if (memberVO != null) {
                ArrayList<String> authList = memberRolesMapper.getMemberRoles(memberVO.getMemberId());

                List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
                for (String role : authList) {
                    System.out.println(role);
                    authorities.add(new GrantedAuthorityImpl(role.toString()));
                }

                if (memberVO.getEnabled()) {
                    User user = new User(memberVO.getUserName(), memberVO.getPassword(), true, true, true, true, authorities);
                    return user;
                } else {
                    logger.error("User with login: " + userName + " not Enabled in database. Authentication failed for user ");
                    throw new UsernameNotFoundException("User Not Enabled");
                }
            } else {
                logger.error("User with login: " + userName + " not found in database. Authentication failed for user ");
                throw new UsernameNotFoundException("user not found in database");
            }
        } else {
            logger.error("No User specified in the login ");
            throw new UsernameNotFoundException("No username specified");
        }

    }
}

ここで2つのことに注意してください。

  1. ユーザーの詳細(私の場合はDBから取得します)を取得し、それを新しいorg.springframework.security.core.userdetails.Userオブジェクトの下に置きます。このオブジェクトは、メソッドによってSpringSecurityに返されます。
  2. また、オーソリティ(DBアーキテクチャに従ってDBとは別にロードしますが、シナリオは異なる場合があります)を使用して、同じユーザーオブジェクトを介してセキュリティを強化します。
于 2012-09-11T09:58:05.477 に答える
0

独自のカスタムAuthenticationManagerおよびカスタムUsernamePasswordAuthenticationFilterを実装できます。これは単純な例ですが、これはセキュリティコンテキストの非常に機密性の高い部分であるというあなたの情報についてもアイデアを与えることができます:)

spring_security.xmlにBeanを作成するだけです。

<http entry-point-ref="authenticationProcessingFilterEntryPoint"
        use-expressions="true">

        <custom-filter ref="sessionManagementFilter" before="SESSION_MANAGEMENT_FILTER" />
        <custom-filter ref="customUsernamePasswordAuthenticationFilter"
            position="FORM_LOGIN_FILTER" />

        <session-management
            session-authentication-strategy-ref="sas"></session-management>
    </http>


    <beans:bean id="authenticationProcessingFilterEntryPoint"
            class="org.springframework.security.web.authentication.AuthenticationProcessingFilterEntryPoint">
            <beans:property name="loginFormUrl" value="/login" />
        </beans:bean>

        <beans:bean id="sas"
            class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />

        <beans:bean id="customAuthenticationManager"
            class="my.package.security.CustomAuthenticationManager" />

        <beans:bean id="customUsernamePasswordAuthenticationFilter"
            class="my.package.security.CustomUsernamePasswordAuthenticationFilter">

            <beans:property name="sessionAuthenticationStrategy"
                ref="sas" />

            <beans:property name="authenticationManager" ref="customAuthenticationManager" />


            <beans:property name="authenticationSuccessHandler">

                <beans:bean
                    class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">

                    <beans:property name="defaultTargetUrl" value="/main.xhtml" />

                </beans:bean>

            </beans:property>

            <beans:property name="authenticationFailureHandler">

                <beans:bean
                    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">

                    <beans:property name="defaultFailureUrl" value="/login.xhtml" />

                </beans:bean>

            </beans:property>
        </beans:bean>
<beans:bean id="sessionManagementFilter"
        class="org.springframework.security.web.session.SessionManagementFilter">
        <beans:constructor-arg name="securityContextRepository"
            ref="httpSessionSecurityContextRepository" />
    </beans:bean>
    <beans:bean id="httpSessionSecurityContextRepository"
        class="org.springframework.security.web.context.HttpSessionSecurityContextRepository" />

CustomUsernamePasswordAuthenticationFilterを実装する場合、認証をオーバーライドし、外部ロジックを追加します。

public final class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

@Override
    public Authentication attemptAuthentication(HttpServletRequest request,   HttpServletResponse response){
CustomAuthentication auth = new CustomAuthentication();

            // set details of current user
            auth.setDetails(new WebAuthenticationDetails(request));
            auth.setAuthenticated(true);
            auth.setUserName(username);

            // set authentication to current security session
            LOGGER.info("Setting authentication into existing security context");
            SecurityContextHolder.getContext().setAuthentication(auth);

            // if validation done return generated authentication
            return auth;

}

}

次に、生成された認証オブジェクトは認証マネージャーによって処理されます。

public final class CustomAuthenticationManager implements AuthenticationManager {

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.security.authentication.AuthenticationManager#
     * authenticate(org.springframework.security.core.Authentication)
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(CustomUsernamePasswordAuthenticationFilter.class);
    private final BadCredentialsException badCredentialsException = new BadCredentialsException("Invalid username/password");
    @Override
    public Authentication authenticate(Authentication authentication) {

        //check if user has valid authentication
        if (authentication == null) {
            LOGGER.debug("Null authentication");
            throw badCredentialsException;
        }
        //Check mandatory fields
        if (!Validator.isValidString((String) authentication.getPrincipal()) || !Validator.isValidString((String) authentication.getCredentials())) {
            LOGGER.debug("Null/blank username/credential");
            throw badCredentialsException;

        }
        //Check if there is any role assigned into user
        if (authentication.getAuthorities() != null && authentication.getAuthorities().size() < 1) {
            LOGGER.debug("No authority found");
            throw badCredentialsException;
        }

        //Validate role
        //IF ROLE VALIDATION REQUIRED YOU CAN HANDLE IT HERE
        boolean authorityValid = false;
        LOGGER.info("Validating user authentication. Total grantedAuth size: " + authentication.getAuthorities().size());
        for (GrantedAuthority g : authentication.getAuthorities()) {
            if (!authorityValid) {
                //Testing purpose one type role available, when exact roles prepared create enum types
                authorityValid = g.getAuthority().equals("ROLE_LDAP_AUTHENTICATED");
            }
        }

        //if none of role matching to required throw exception
        if(!authorityValid){
            LOGGER.debug("User has authority but none of them matching");
            throw badCredentialsException;
        }

        LOGGER.info("Final validation done returning authentication");
        return authentication;
    }

}

次に、必要に応じて、デフォルトの認証オブジェクトをオーバーライドすることもできます。ここで動的に配置されたロールが処理する場所である場合:

public final class CustomAuthentication implements Authentication {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private transient String userName;
        private transient boolean authenticated;
        private transient Object details;
        private static final transient String ROLE = "ROLE_LDAP_AUTHENTICATED";

        /*
         * (non-Javadoc)
         * 
         * @see java.security.Principal#getName()
         */
        @Override
        public String getName() {
            return this.userName; //for dynamic username logic here
        }



     //IF ROLES DYNAMICALLY ALLOCATED ASSIGN IT HERE, HERE IS WHERE YOU READ FROM INTERCEPT URL

        /*
         * (non-Javadoc)
         * 
         * @see org.springframework.security.core.Authentication#getAuthorities()
         */
        @Override
        public Collection<GrantedAuthority> getAuthorities() {
            Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
            auths.add(new GrantedAuthority() {

                /**
                 * 
                 */
                private static final long serialVersionUID = 1L;

                @Override
                public String getAuthority() {
                    if (authenticated) {

                        return ROLE;
                    }
                    return null;
                }
            });
            return auths;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.springframework.security.core.Authentication#getCredentials()
         */
        @Override
        public Object getCredentials() {
            //TODO: a specific algorithm can be stored
            return userName + " is ldap authenticated user";
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.springframework.security.core.Authentication#getDetails()
         */
        @Override
        public Object getDetails() {
            return this.details;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.springframework.security.core.Authentication#getPrincipal()
         */
        @Override
        public Object getPrincipal() {
            return userName;
        }

        /*
         * (non-Javadoc)
         * 
         * @see org.springframework.security.core.Authentication#isAuthenticated()
         */
        @Override
        public boolean isAuthenticated() {

            return this.authenticated;
        }

        /*
         * (non-Javadoc)
         * 
         * @see
         * org.springframework.security.core.Authentication#setAuthenticated(boolean
         * )
         */
        @Override
        public void setAuthenticated(boolean arg0) {
            this.authenticated = arg0;

        }

        public String getUserName() {
            return userName;
        }

        public void setUserName(String userName) {
            this.userName = userName;
        }

        public void setDetails(Object details) {
            this.details = details;
        }

    }
于 2012-09-11T10:25:03.460 に答える
0

ユーザー情報を保持するサービスを実装します。

@Service
public class UserAuthenticationInfoService {

    private final Map<String, UserInfo> infos = new HashMap<String, UserInfo>();

    public void addUserInfo(UserInfo userInfo){
        infos.put(userInfo.getUsername(), userInfo);   
    }

    public UserInfo getUserInfo(String username) {
        return infos.get(username);
    }

}

コントローラーは、外部アプリケーションから受け取ったユーザー情報を UserAuthenticationInfoService サービスに取り込みます。

次に、カスタム UserDetailsS​​ervice を実装して、これらの情報にアクセスします。

public class CustomerUserDetailsService implements UserDetailsService {
    @Autowired
    private UserAuthenticationInfoService service;

     public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {
        UserInfo info = service.getUserInfo(userName);
        return new User(info.getUsername(), info.getPassword(), info.getAuthorities());
    }
}

この UserDetailsS​​ervice を使用するように春のセキュリティ コンテキストをセットアップします (春のセキュリティ ドキュメントに記載されています)。

于 2012-09-11T10:50:26.313 に答える