I've got a somewhat complicated user authentication requirement I'm
attempting to use Shiro for.

We have an LDAP Active Directory setup which we want to authenticate
against. We have a separate JDBC system we wish to authorize against without
using a password after they have been authenticated in LDAP.

Figuring out how to make that happen has been something we've been looking
into for at least a month, and we haven't been successful. The current issue
I am having is that LDAP seems to "infect" the system, meaning I cannot ask
Shiro to do /anything/ against the JDBC realm once it does something in the
LDAP realm. Even if I strip out all of the LDAP code and delete the ini
file, even if the JDBC realm is built programattically I still get "LDAP
Authentication Failed". I'm using Glassfish 4, and even redeployment doesn't
seem to work. 

Now it is possible that restarting the instance will do the trick, but this
still leaves me with the problem with the dual realm setup. I try to run
GetPer function after running isAuthorized and get the LDAP issue, even
though I'm not calling the ini file at all.

The main issue here is that I'm getting an LDAP error when if any error
occurs it should be JDBC. I changed some of the code below for security
reasons, so there may be a few things slightly off, but that shouldn't
affect the LDAP error.

Here is my code:

public class Authentication {
        private static final transient Logger log =
LoggerFactory.getLogger(Authentication.class);
        Subject currentUser = null;
        String username = "";
        String password = "";
        public Boolean isAuthenticated(String un, String pw){
            username = un;
            password = pw;
            try{
                log.info("Log: |");
                System.setProperty("log4j.category.org.apache.shiro",
"DEBUG");          
                Factory<SecurityManager> factory = new
IniSecurityManagerFactory("classpath:shiro.ini");
                SecurityManager securityManager = factory.getInstance();
                SecurityUtils.setSecurityManager(securityManager);
                ensureUserIsLoggedOut();
                currentUser = SecurityUtils.getSubject();
            }catch(Exception e){
                String error = e.toString();
            }
            Boolean  b = false;
            try{
                if (!currentUser.isAuthenticated()) {

                    UsernamePasswordToken token = new
UsernamePasswordToken(username, password);
                    
                    try {                        
                        currentUser.login(token);                         
                        b = true;
                    }catch (UnknownAccountException uae) {
                        b =  false;
                        log.info("There is no user with username of " +
token.getPrincipal().toString());
                        log.info("uae error: " + uae.toString());
                        
                    } catch ( IncorrectCredentialsException ice ) {
                        b =  false;
                    } catch ( LockedAccountException lae ) {
                        b =  false;
                    }
                }else{
                    b = true;
                }
            }catch (AuthenticationException ae) {
                b = false;
                log.info(ae.toString());
            }catch(Exception e){
                b = false;
                log.info( e.toString());
            }
            // Do some stuff with a Session (no need for a web or EJB
container!!!)
            //SecurityUtils.getSubject().logout();
            return b;
        }

private void ensureUserIsLoggedOut()
{
    try
    {
        // Get the user if one is logged in.
        Subject currentUser = SecurityUtils.getSubject();
        if (currentUser == null)
            return;

        // Log the user out and kill their session if possible.
        currentUser.logout();
        Session session = currentUser.getSession(false);
        if (session == null)
            return;

        session.stop();
    }
    catch (Exception e)
    {
        // Ignore all errors, as we're trying to silently 
        // log the user out.
    }
}


 public Boolean getPer(String un, String Permission){
            System.setProperty("log4j.category.org.apache.shiro", "DEBUG");     
     
            DataSource ds = null;
            try{
                Context ctx = new InitialContext();
                ds = (DataSource)ctx.lookup("jdbc/MyDataSource");
            }catch(Exception e){
                log.info("DataSource issue: " + e.toString());
            }
            Subject User = null;
            JdbcRealm realm = new org.apache.shiro.realm.jdbc.JdbcRealm();

            realm.setDataSource(ds);
            realm.setAuthenticationQuery("SELECT pw FROM UT where username =
?");
            realm.setUserRolesQuery("SELECT R.rn from UT left join UTR on
ut.user_id = utr.user_id left join UR R on utr.role_id = R.role_name where
ut.username = ?");
            realm.setPermissionsQuery("SELECT pn FROM UP P join PTR  on
P.permission_id = PTR.permission_id join UserRole R on PTR.role_id =
R.role_name WHERE R.rn= ?");
            realm.setPermissionsLookupEnabled(true);
            
            DefaultHashService hashService = new
org.apache.shiro.crypto.hash.DefaultHashService();
            hashService.setHashIterations(500000);
            hashService.setHashAlgorithmName("SHA-256");
            hashService.setGeneratePublicSalt(true);
            hashService.setPrivateSalt(new SimpleByteSource("TheSalt"));
            PasswordMatcher passwordMatcher = new
org.apache.shiro.authc.credential.PasswordMatcher();
            
            DefaultPasswordService ps = new
org.apache.shiro.authc.credential.DefaultPasswordService();
            
            passwordMatcher.setPasswordService(ps);
            realm.setCredentialsMatcher(passwordMatcher);
            
                       
            DefaultSecurityManager securityManager = new
DefaultSecurityManager(realm);
            SecurityUtils.setSecurityManager(securityManager);           
            Boolean b = false;
            UsernamePasswordToken token = null;
            
            try{
                User = SecurityUtils.getSubject();
                if (User == null || !User.isAuthenticated()) {

                    token = new UsernamePasswordToken(username, password);
                    User.login(token); 
                }
                try {                        
                    if(User.isPermitted("Admin")){
                        b = true;
                    }else{
                        b = User.isPermitted(Permission);
                    }
                       //b = currentUser.hasRole("5");
                }catch (UnknownAccountException uae) {
                    b =  false;
                    log.info("There is no user with username of " +
token.getPrincipal().toString());
                } catch ( IncorrectCredentialsException ice ) {
                    b =  false;
                } catch ( LockedAccountException lae ) {
                    b =  false;
                    //account for that username is locked - can't login. 
Show them a message?
                }
                
            }catch (AuthenticationException ae) {
                String e = ae.toString();
                log.info(e);
            }catch(Exception e){
                String error = e.toString();
                log.info("Main error: " + error);
            }
            // Do some stuff with a Session (no need for a web or EJB
container!!!)
            //SecurityUtils.getSubject().logout();
            return b;
        }



--
View this message in context: 
http://shiro-developer.582600.n2.nabble.com/Shiro-Always-Authenticates-Against-LDAP-tp7579740.html
Sent from the Shiro Developer mailing list archive at Nabble.com.

Reply via email to