【问题标题】:Multiple authentication with spring security具有弹簧安全性的多重身份验证
【发布时间】:2015-09-04 04:06:43
【问题描述】:

我有一个包含两个字段的应用程序:管理员和候选人。

我已经在候选部分中实现了 spring 安全性并且它可以工作,但是当我想在管理员的身份验证中实现另一个安全性时,它不起作用。

我有两个认证页面

这是我的安全码:

    <security:http  use-expressions="true" auto-config="true" 
access-denied-page="/404.xhtml" >

    <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/candidat.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/aproposdemoi.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/chargermoncv.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/completermonprofil.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/maphotodeprofil.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/mescompetences.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/mesexperiences.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/meslangues.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/moncompte.xhtml" />
        <security:intercept-url access="hasAnyRole('candidat')"
        pattern="/supprimercompte.xhtml" />

    <security:form-login login-processing-url="/j_spring_security_check" 
        login-page="/carrieres?login_error=1" always-use-default-target="true"
        default-target-url="/candidat.xhtml" />     
    <security:logout logout-success-url="/carrieres.xhtml" />   
    <security:remember-me key="uniqueAndSecret"/>



    <security:form-login login-processing-url="/j_spring_security_check" 
        login-page="/adminzone?login_error=1" always-use-default-target="true"
        default-target-url="/tableaudebord.xhtml" />        
    <security:logout logout-success-url="/adminzone.xhtml" />   
    <security:remember-me key="uniqueAndSecret"/>
</security:http>




  <security:authentication-manager>
    <security:authentication-provider>
        <security:password-encoder hash="md5" />
        <security:jdbc-user-service id="jdbcMemoryAP"
            data-source-ref="dataSource"
            users-by-username-query="
          select email_candidat,mot_de_passe_candidat,enabled  
          from candidat where email_candidat=?"
            authorities-by-username-query="
          select u.email_candidat, ur.autorite from candidat u, role_candidat ur 
          where u.id_candidat = ur.candidat and u.email_candidat =? " />
    </security:authentication-provider>     
</security:authentication-manager>


 <security:authentication-manager >
    <security:authentication-provider>
        <security:password-encoder hash="md5" />
        <security:jdbc-user-service id="jdbcMemoryAP"
            data-source-ref="dataSource"
            users-by-username-query="
          select email_admin,mot_de_passe,enabled  
          from administrateur where email_admin=?"
            authorities-by-username-query="
          select u.email_admin, ur.autorite from administrateur u, role_administrateur ur 
          where u.idAdmin = ur.administrateur and u.email_admin =? " />
    </security:authentication-provider>     
</security:authentication-manager>

【问题讨论】:

  • 那是一些乱七八糟的东西,我的朋友。首先,您是否有一些地方可以控制谁可以在 Java 代码中访问。您可以使用@PreAuthorize。你说的字段是什么意思?那些不同的类,表?您是如何实现身份验证或 UserDetails 的,或者以任何方式实现的。
  • 是的,我有两个表 admin 和 Candidate,当我只测试 admin 中的安全性时它可以工作,但是当我想为 admin 和应聘者设置安全性时,它不起作用。跨度>
  • 好的,我会为你发布一个答案,但它也涉及java代码。给我 15 岁。
  • 好的,谢谢。 java代码无关紧要。
  • 嗯,这应该很重要,因为没有它就无法工作......:D

标签: spring spring-security


【解决方案1】:

所以,任何时候你必须通过两个表登录,表的模型类都应该实现 UserDetails。每个表,您将需要一个 LoginService。

Security-applicationContext.xml:

// The 2 providers mentioned below are each for different datbase tables. Please //note, tables will be checked sequentially. 
  <security:authentication-manager alias="authenticationManager">
        <security:authentication-provider ref="daoAuthenticationProvider"/>
          <security:authentication-provider ref="hostAuthenticationProvider"/>
    </security:authentication-manager>

    <beans:bean id="encoder"
                class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
        <beans:constructor-arg name="strength" value="strengthInInteger you want, default 6" />
    </beans:bean>

    <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
//Below is the first LoginServiceImpl, a java bean I have declared in //applicationContext.xml, not here.
        <beans:property name="userDetailsService" ref="LoginServiceImpl"/>
        <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>

    <beans:bean id="hostAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
//Below is the second Login implementation, a java bean I have declared in //applicationContext.xml, not here.
        <beans:property name="userDetailsService" ref="HostLoginServiceImpl"/>
        <beans:property name="passwordEncoder" ref="encoder"/>
    </beans:bean>

现在,

// 注意第一个 LoginServiceImpl 实现了 UserDetailsS​​ervice。该文件负责检查 db 中是否有任何具有给定用户名的学生。如果是,那么我们构建一个 Spring-security 可以理解的 User 对象,我将在此文件之后粘贴代码。

@Transactional
@Service("userDetailsService")
public class LoginServiceImpl implements UserDetailsService{

    @Autowired private StudentDAO studentDAO;
    @Autowired private Assembler assembler;

    private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_STUDENT");

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        Student student = this.studentDAO.findStudentByUsername(username);
            if(student == null) { throw new UsernameNotFoundException("Wrong username or password");}
        return assembler.buildUserFromUserEntity(student);
    }
}

现在,当找到用户时,只有我们调用它。

@Service("assembler")
public class Assembler {
    @Transactional(readOnly = true)
    User buildUserFromUserEntity(Student userEntity){
        String username = userEntity.getUsername();
        String password = userEntity.getPassword();

        // Long id = userEntity.getId();
      //  boolean enabled = userEntity.isActive();
        boolean enabled = true;
        boolean accountNonExpired = userEntity.isAccountNonExpired();
        boolean credentialsNonExpired = userEntity.isCredentialsNonExpired();
        boolean accountNonLocked = userEntity.isAccountNonLocked();

        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority("ROLE_STUDENT"));

        User user = new User(username,password,enabled,accountNonExpired,credentialsNonExpired,accountNonLocked,authorities);
        return  user;
        }
}

以类似的方式,我有第二个,即 HostLoginService :

@Transactional
@Service("hostuserDetailsService")
public class HostLoginService implements UserDetailsService{

    @Autowired
    private HostDAO hostDAO;
    @Autowired
    private HostAssembler assembler;

    private static final GrantedAuthority USER_AUTH = new SimpleGrantedAuthority("ROLE_HOST");

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,DataAccessException {
        Host host = this.hostDAO.findHostByUsername(username);
        if(host == null) { throw new UsernameNotFoundException("Wrong username or password");}
        return assembler.buildUserFromUserEntity(host);
    }
}

为简洁起见,我避免使用它的汇编程序。

现在您可以看到角色不同了。为了正确的重定向,您必须为 Spring-Security 的 default-target-url 创建一个控制器方法,通过查询 Spring-security 来检查谁是当前经过身份验证的、管理员或候选人。然后你可以重定向。

如果有任何疑问,请告诉我。

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 1970-01-01
    • 2012-02-15
    • 2014-05-20
    • 2014-03-06
    • 2017-04-13
    • 2017-09-22
    • 2015-12-06
    • 2020-06-21
    相关资源
    最近更新 更多