How to get the user entered values of username and

2019-02-11 05:09发布

问题:

I use Spring MVC in my application and the login is authenticated by spring security. I have the following two methods in my UserServiceImpl.java class, public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {

        ApplicationTO applicationTO = null;
        try
            {
                applicationTO = applicationService.getApplicationTO(adminDomainName);
            }
        catch (ApplicationPropertyException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        UserTO userTO = getUserTO(applicationTO.getApplicationId(), userName);
        if (userTO == null)
            {
                throw new UsernameNotFoundException("user not found");
            }
        httpSession.setAttribute("userTO", userTO);
        return buildUserFromUserEntity(userTO);
    }


User buildUserFromUserEntity(UserTO userTO)
            {
                String username = userTO.getUsername();
                String password = userTO.getPassword();
                int userId = userTO.getUserId();
                int applicationId = userTO.getApplicationId();
                boolean enabled = userTO.isEnabled();
                boolean accountNonExpired = true;
                boolean credentialsNonExpired = true;
                boolean accountNonLocked = true;
                User user = new User(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthority(applicationId, userId));
                return user;
            }

I am relatively new to Spring and do not have much idea about the spring security part. In my spring-security.xml file, I have the following,

<form-login login-page="/login" default-target-url="/module/user-home/welcome"
    authentication-failure-url="/login?error" username-parameter="username"
    password-parameter="password" />
<logout logout-success-url="/login?logout" />

<beans:bean id="daoAuthenticationProvider"
 class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>

<beans:bean id="authenticationManager"
    class="org.springframework.security.authentication.ProviderManager">
  <beans:property name="providers">
    <beans:list>
      <beans:ref local="daoAuthenticationProvider" />
    </beans:list>
  </beans:property>
</beans:bean>

And my login form has the action set as follows:

<form id="loginForm" class="form-horizontal" role="form" name='loginForm' action="${rc.getContextPath()}/j_spring_security_check" method='POST'>

Now I am trying to get the value of the password that the user has entered in the login form, either inside the loadUserByUsername method or by adding a new method to the UserServiceImpl.java class.

I use the following to encrypt my passwords before saving them. What API and algorithm to be used to encrypt and decrypt a password using java

So during login, spring security compares the user entered password with encrypted password from the database and the login fails. But as per the implementation suggested in the above link, there is a method to compare the password and the encrypted password to check if they are same. That is possible only if I get access to the user entered password. This is the reason I am trying to get the user entered password.

回答1:

As was suggested in answer by MangEngkus you can implement your own custom AuthenticationProvider but based on your description I don't think you need to do that.

You don't need to implement your own password hashing mechanism into spring-security. You just need to define BCryptPasswordEncoder from spring itself.

Either this way to use the default one:

<authentication-manager>
  <authentication-provider>
    <password-encoder hash="bcrypt" />
  </authentication-provider>
</authentication-manager>

Or create your own bean and supply it to default provider:

<authentication-manager>
  <authentication-provider>
    <password-encoder ref="encoder" />
  </authentication-provider>
</authentication-manager>

<beans:bean id="encoder" 
  class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
    <beans:constructor-arg name="strength" value="15" />
</beans:bean>

But for you, this is the way: :)

<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
  <beans:property name="userDetailsService" ref="userDetailsService"/>
  <beans:property name="passwordEncoder" ref="encoder" />
</beans:bean>

<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>


回答2:

if you want, you can create your own AuthenticationProvider

public class CustomAuthenticationProvider implements AuthenticationProvider{

    private UserDetailsService service;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;
        String username = token.getName();
        String password = token.getCredentials(); // retrieve the password 
        // do something here

        // if ok then return the authentication
        return new UsernamePasswordAuthenticationToken(username, password, authorities);
    }
}

and plug it to your security configuration

<beans:bean id="customAuthenticationProvider"
 class="com.xxx.CustomAuthenticationProvider">
  <beans:property name="userDetailsService" ref="userDetailsService"/>
</beans:bean>

<beans:bean id="authenticationManager"
    class="org.springframework.security.authentication.ProviderManager">
  <beans:property name="providers">
    <beans:list>
      <beans:ref local="customAuthenticationProvider" />
    </beans:list>
  </beans:property>
</beans:bean>