簡體   English   中英

Spring Security自定義登錄

[英]Spring security custom login

我試圖用三個值創建一個登錄頁面:

  1. 用戶名
  2. 密碼
  3. 公司名

我的應用程序支持不同的公司,並且一個用戶可能是多個公司的用戶,因此,在登錄頁面中,作為登錄的一部分,用戶必須選擇要登錄的公司。

這是我目前正在使用的:

  1. Java 8
  2. Spring 4.0.3.RELEASE(我正在使用xmls文件)
  3. Spring Security 4.0.3。發布
  4. 休眠4.2.21。最終
  5. 胸腺2.1.4。發布

這是我的spring-security.xml

<b:beans xmlns="http://www.springframework.org/schema/security"
         xmlns:b="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-4.1.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security.xsd">


    <b:bean id="passwordEncoder"
            class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
        <b:constructor-arg value="256"/>
        <b:property name="iterations" value="8224"/>
    </b:bean>

    <!-- Define the User property to use for salting password encoding -->
    <b:bean id="saltSource"
            class="org.springframework.security.authentication.dao.ReflectionSaltSource">
        <b:property name="userPropertyToUse" value="userSalt"/>
    </b:bean>

    <b:bean id="userCompanyAuthenticationProvider"
            class="com.mycompany.security.authentication.UserCompanyAuthenticationProvider">

    </b:bean>

    <!--Authentication provider to use for Spring Security-->
    <!--<b:bean id="daoAuthenticationProvider" -->
    <!--class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">-->
    <!--&lt;!&ndash; userDetailsService is annotated at com.mycompany.security.userdetails.UserDetailsServiceImpl &ndash;&gt;-->
    <!--<b:property name="userDetailsService" ref="userDetailsService"/>-->
    <!--<b:property name="passwordEncoder" ref="passwordEncoder"/>-->
    <!--<b:property name="saltSource" ref="saltSource"/>-->
    <!--</b:bean>-->

    <b:bean id="authenticationEntryPoint"
            class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/>

    <!--<authentication-manager alias="authenticationManager">-->
    <!--<authentication-provider ref="daoAuthenticationProvider" />-->
    <!--</authentication-manager>-->


    <!-- Turn off Spring Security for the following URL/patterns -->

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

    <!-- Configure the HTTP realm/security settings and enable SpEL expressions -->
    <http use-expressions="true" auto-config="false" entry-point-ref="loginEntryPoint">

        <custom-filter ref="userCompanyFormLoginFilter"
                       position="FORM_LOGIN_FILTER"/>
        <csrf disabled="true"/>
        <!-- Enable remember me cookie functionality -->
        <!--<remember-me key="myappRememberMe"-->
                     <!--token-validity-seconds="2419200"/>-->

        <intercept-url pattern="/favicon.ico" access="permitAll"/>
        <intercept-url pattern="/login" access="permitAll"/>
        <intercept-url pattern="/logout" access="permitAll"/>
        <intercept-url pattern="/auth/**" access="permitAll"/>
        <intercept-url pattern="/signup/**" access="permitAll"/>
        <intercept-url pattern="/static/**" access="permitAll"/>
        <intercept-url pattern="/resources/**" access="permitAll"/>
        <intercept-url pattern="/_ui/**" access="permitAll"/>

        <intercept-url pattern="/user" access="hasRole('ROLE_USER')"/>

        <intercept-url pattern="/admin" access="hasRole('ROLE_ADMIN')"/>

        <intercept-url pattern="/**" access="isAuthenticated()"/>

        <access-denied-handler ref="customAccessDeniedHandler"/>

        <!-- Login Page -->
        <!--<form-login login-page="/login" default-target-url="/"-->
        <!--login-processing-url="/static/j_spring_security_check"-->
        <!--authentication-failure-url="/login?error=true" />-->

        <!-- URL for logging out and specific cookies to delete when doing so. -->
        <!--<logout logout-url="/logout" delete-cookies="JSESSIONID"/>-->
        <!-- delete-cookies="JSESSIONID, SPRING_SECURITY_REMEMBER_ME_COOKIE" -->

        <session-management>
            <concurrency-control max-sessions="1"
                                 error-if-maximum-exceeded="false"/>
        </session-management>
    </http>

    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="userCompanyAuthenticationProvider"/>
    </authentication-manager>

    <b:bean id="userCompanyFormLoginFilter" class="com.mycompany.security.filter.UserCompanyAuthenticationFilter">
        <b:property name="filterProcessesUrl" value="/login/form"/>
        <b:property name="authenticationManager" ref="authenticationManager"/>
        <b:property name="usernameParameter" value="username"/>
        <b:property name="passwordParameter" value="password"/>
    </b:bean>

    <b:bean id="loginEntryPoint"
            class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <b:constructor-arg value="/login"/>
    </b:bean>

    <b:bean id="customAccessDeniedHandler" class="com.mycompany.security.AccessDeniedHandlerApp"/>
</b:beans>

這是我的UserCompanyAuthenticationFilter

package com.mycompany.security.filter;
import com.mycompany.security.authentication.UserCompanyAuthenticationToken;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class UserCompanyAuthenticationFilter extends UsernamePasswordAuthenticationFilter
{

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

        String username = obtainUsername(request);
        String password = obtainPassword(request);
        String company = request.getParameter("company");

        UserCompanyAuthenticationToken authRequest = new UserCompanyAuthenticationToken(username, password, company);

        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

}

這是我的UserCompanyAuthenticationProvider:

package com.mycompany.security.authentication;
import com.mycompany.entity.User;
import com.mycompany.myapp.dao.service.CompanyService;
import com.mycompany.myapp.dao.service.LoginService;
import com.mycompany.security.RoleEnumerator;
import com.mycompany.security.UnknownRoleException;
import org.apache.log4j.Logger;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;

public class UserCompanyAuthenticationProvider implements AuthenticationProvider
{

    private LoginService loginService;

    private CompanyService companyService;

    private static final Logger LOGGER = Logger.getLogger(UserCompanyAuthenticationProvider.class);

    @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        UserCompanyAuthenticationToken token = (UserCompanyAuthenticationToken) authentication;
        String username = token.getName();
        String company = token.getCompany();

        User user = null;
        if (username != null)
        {
            user = loginService.getByUsername(username, companyService.get(Long.parseLong(company)));
        }

        if (user == null)
        {
            throw new BadCredentialsException("Invalid username - password");
        }

        String password = user.getPasswordHash();

        if (!loginService.isValidUsernameAndPasswordHashCombination(username, password))
        {
            throw new BadCredentialsException("Invalid username - password");
        }

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        try
        {
            RoleEnumerator.getApplicableRoles(user)
                    .forEach(role -> authorities.add(new SimpleGrantedAuthority(role.toString())));

        }
        catch (UnknownRoleException rex)
        {
            LOGGER.error(rex.getMessage(), rex);
        }

        return new UserCompanyAuthenticationToken(user.getUsername(), password, authorities, company);

    }

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

    @Inject public void setLoginService(LoginService loginService)
    {
        this.loginService = loginService;
    }

    @Inject public void setCompanyService(CompanyService companyService)
    {
        this.companyService = companyService;
    }

}

這是我的UserCompanyAuthenticationToken

package com.mycompany.security.authentication;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

public class UserCompanyAuthenticationToken extends UsernamePasswordAuthenticationToken
{
    private final String company;

    public UserCompanyAuthenticationToken(String principal, String credentials, String company)
    {
        super(principal, credentials);
        this.company = company;
    }

    public UserCompanyAuthenticationToken(String principal, String credentials,
            Collection<? extends GrantedAuthority> authorities, String company)
    {
        super(principal, credentials, authorities);
        this.company = company;
    }

    public String getCompany()
    {
        return company;
    }
}

到目前為止,我已經在httprequest中發送了三個值(用戶名,密碼和公司),並且一切正常。

但是,密碼未編碼,我想做的是對密碼進行編碼並發送saltSource以便比較密碼和salt。

有人有一個關於如何執行此操作的示例嗎?或者有人對如何執行此操作有任何建議或指示嗎?

提前致謝

我進行了以下更改(目前,因為我將使用BCryptPasswordEncoder作為推薦的@szymon)

這是我的security.xml:

 <b:bean id="passwordEncoder"
            class="org.springframework.security.authentication.encoding.ShaPasswordEncoder">
        <b:constructor-arg value="256"/>
        <b:property name="iterations" value="8224"/>
    </b:bean>

   <b:bean id="userCompanyAuthenticationProvider"
            class="com.digitalkresko.security.authentication.UserCompanyAuthenticationProvider">
        <b:property name="passwordEncoder" ref="passwordEncoder"/>
    </b:bean>

然后,我在UserCompanyAuthenticationProvider中進行了以下更改:

public class UserCompanyAuthenticationProvider implements AuthenticationProvider
{

    private LoginService loginService;

    private CompanyService companyService;

    **private ShaPasswordEncoder passwordEncoder;**

    private static final Logger LOGGER = Logger.getLogger(UserCompanyAuthenticationProvider.class);

    @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException
    {
        UserCompanyAuthenticationToken token = (UserCompanyAuthenticationToken) authentication;
        String username = token.getName();
        String company = token.getCompany();

        User user = null;
        if (username != null)
        {
            user = loginService.getByUsername(username, companyService.get(Long.parseLong(company)));
        }

        if (user == null)
        {
            throw new BadCredentialsException("Invalid username - password");
        }

        String password = passwordEncoder.encodePassword(token.getCredentials().toString(), user.getUserSalt());

        if (!loginService.isValidUsernameAndPasswordHashCombination(username, password))
        {
            throw new BadCredentialsException("Invalid username - password");
        }

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        try
        {
            RoleEnumerator.getApplicableRoles(user)
                    .forEach(role -> authorities.add(new SimpleGrantedAuthority(role.toString())));

        }
        catch (UnknownRoleException rex)
        {
            LOGGER.error(rex.getMessage(), rex);
        }

        return new UserCompanyAuthenticationToken(user.getUsername(), password, authorities, company);

    }

但是,我不確定這是否是驗證用戶名/密碼的正確方法。 你怎么看?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM