开发者

loadUserByUsername is not invoked

开发者 https://www.devze.com 2023-04-12 14:26 出处:网络
i am using spring security 3 when i enter wrong data user is redirected to login-failure-link but spring security doesn\'t invoke the loadUserByUsername method ?

i am using spring security 3 when i enter wrong data user is redirected to login-failure-link but spring security doesn't invoke the loadUserByUsername method ? so how does the authentication happens and spring knows that credentials are wrong ? or i have something wrong with my configuration, please guide.

login page:

<form action="/myapp/j_spring_security_check">
                        <h:graphicImage id="graphicImage1" style="height: 322px; left: 0px; top: 0px; position: absolute" url="/resources/images/LoginImage.jpg" width="560"/>
                        <h:outputLabel for="j_username" id="outputLabel1" style="left: 48px; top: 120px; position: absolute" value="Username:"/>
                        <h:outputLabel for="j_password" id="outputLabel2" style="left: 48px; top: 168px; position: absolute" value="Password:"/>
                        <h:inputText binding="#{login.username}" id="j_username" required="true"
                            style="left: 142px; top: 118px; position: absolute; width: 237px" />
                        <h:inputSecret binding="#{login.password}" id="j_password" required="true" style="left: 142px; top: 166px; position: absolute; width: 237px"/>
                        <h:commandButton   id="loginBtn" style="left: 144px; top: 240px; position: absolute" value="Login"/>
                        <h:commandButton action="#{login.reset}" id="resetBtn" style="position: absolute; left: 360px; top: 240px" value="Reset"/>
                        <h:outputText id="errorMessage" style="left:0px;top:300px;position:absolute"/>
                        <h:message errorClass="errorMessage"  for="j_username" fatalClass="fatalMessage" id="messages1" infoClass="infoMessage" showSummary="false"
                            style="height: 43px; left: 24px; top: 288px; position: absolute; width: 523px;color:red;" warnClass="warnMessage"/>
                      </form>

security.xml:

<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.1.xsd
          http://www.springframework.org/schema/security
          http://www.springframework.org/schema/security/spring-security-3.0.4.xsd">


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

        <!--  key configuration here is an entry point to be used by security intercepts -->
        <http use-expressions="true"  auto-config="false">

        <session-management session-fixation-protection="none"/>

        <remember-me  token-validity-seconds="1209600"/>

        <!-- Exclude the login page from the security check -->
        <intercept-url pattern="/faces/login.xhtml" access="permitAll"/>

        <!-- All pages requires authentication (not anonymous user) -->
        <intercept-url pattern="/faces/**" access="isAuthenticated()" />

        <intercept-url pattern="/faces/javax.faces.resource/*开发者_StackOverflow中文版*" filters="none" />
        <intercept-url pattern="/faces/xmlhttp/**" filters="none" />
        <intercept-url pattern="/faces/resources/**" filters="none" />
        <intercept-url pattern="/faces/j_spring_security_check/**" filters="none" />
        <intercept-url pattern="/scripts/**" filters="none" />
        <intercept-url pattern="/images/**" filters="none" />
        <intercept-url pattern="/css/**" filters="none" />  

        <!-- Returns true if the user is not anonymous -->


        <access-denied-handler error-page="/error"/>

        <form-login default-target-url="/users"  
        always-use-default-target="true"            
            login-processing-url="/j_spring_security_check"         
            login-page="/faces/login.xhtml"
            authentication-failure-url="/faces/login.xhtml?login_error=1"                                                               
        />

        <logout logout-url="/logout" logout-success-url="/login" />     
    </http>

    <authentication-manager alias="authenticationManager">          
    <authentication-provider user-service-ref="userDetailsServiceImpl">
    </authentication-provider>
    </authentication-manager>


    </beans:beans>

3- UserDetailsService:

@Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        System.out.println("########## LOADING USER ##################");
        User user = userDao.findUserByEmail(username);
        return new org.springframework.security.core.userdetails.User(
                user.getEmail(), user.getPassword(), true, true, true, true,
                setUserAuthorities(user.getAuthorities()));
    }

    public Collection<GrantedAuthority> setUserAuthorities(List<Authority> auths) {

        List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
        for (Authority auth : auths)
            grantedAuthorities.add(new GrantedAuthorityImpl(auth.getName()));
        return grantedAuthorities;
    }
}


You remember that I told that spring security adds a lot of filters? One of that filters is responsible to check that a request for j_spring_security_check is forwared to the Authentication Manager.

But you don't have that filter.

If there is no reason against this, then enable the auto config:

<http use-expressions="true"  auto-config="true">

and add an interceptor for /j_spring_security_check

<intercept-url pattern="/j_spring_security_check" access="permitAll"/>


As I had this

loadUserByUsername is not invoked

and some other problems after upgrading spring security from 3.2.8 to 4.0.2 I'll leave description of my situation even if there already is accepted correct answer.

So yesterday I decided to make mentioned security upgrade. First of all, as in security 4.0.2 csrf protection is enabled by default, I needed to switch it off in mine security-context.xml:

<http>
   .
   .
   .
   <csrf disabled="true"/>
</http>

At current stage of out project csrf protection isn't incorporated in angular UI. This moment lead to error in context initialization.

After that I saw that I can't log into the application. I was making POST to default j_spring_security_check URL for that. But Spring Security 4.0.2 uses another one: Spring Security Reference

login-processing-url Maps to the filterProcessesUrl property of UsernamePasswordAuthenticationFilter. The default value is "/login".

Also default logout-url was changed: Spring Security Reference

logout-url The URL which will cause a logout (i.e. which will be processed by the filter). Defaults to "/logout".

So I made changes to mine security-context.xml and login / logout returned to proper behaviour.

After that I noticed my @PreAuthorize annotations are not working. I'm using them with role names defined as constants:

@PreAuthorize("hasRole(T(org...UserService).ADMIN_ROLE_NAME)"
        + " or hasRole(T(org...UserService).OWNER_ROLE_NAME)")

And role names were:

public final static String ADMIN_ROLE_NAME = "admin";
public final static String USER_ROLE_NAME = "plain_user";
public final static String OWNER_ROLE_NAME = "company_owner";

As You see they did not contain 'ROLE_' prefix. As far as I understand Security 4.0.2 couldn't use such names. May be it's because of: Spring Security Reference

Now you can optionally omit the ROLE_ prefix. We do this to remove duplication. Specifically, since the expression hasRole already defines the value as a role it automatically adds the prefix if it is not there.

I changed role names to:

public final static String ADMIN_ROLE_NAME = "ROLE_ADMIN";
public final static String USER_ROLE_NAME = "ROLE_USER";
public final static String OWNER_ROLE_NAME = "ROLE_OWNER";

and security returned to proper behaviour.

P.S. (upon Ralph's answer)

and add an interceptor for /j_spring_security_check

I didn't have interceptor for 3.2.8 default login-processing-url . And I do not have interceptor for 4.0.2 default login-processing-url. There is interceptor for login page itself in my security-context.xml:

<intercept-url pattern="/authorize" access="permitAll" />

which just returns login.html.


I was also facing the same issue. Then I found out the issue was that I was looking at the same server on a different port which was already running. Verify the port number.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号