2017-01-12 65 views
0

我正在使用Java Hibernate和Apache Shiro進行用戶登錄和驗證。我使用這段代碼來驗證用戶,並按預期工作(據我所知)。使用Apache Shiro登錄驗證的Java Hibernate在「成功」登錄後返回false

try { 
     AuthenticationToken token = new UsernamePasswordToken(user.getUsername().toUpperCase(), user.getPassword()); 


     Subject currentUser = SecurityUtils.getSubject(); 

     Session session = currentUser.getSession(); 
     session.setAttribute("username", user.getUsername()); 
     System.out.println("USER: " + session.getAttribute("username")); 

     currentUser.login(token); 

     System.out.println("User [" + currentUser.getPrincipal() + "] logged in successfully."); 
     System.out.println("Is user authenticated? " + currentUser.isAuthenticated()); 
    } 
    catch (ExcessiveAttemptsException eae) { 
     eae.getStackTrace(); 
     eae.printStackTrace(); 
    } 
    catch (AuthenticationException e) { 
     throw new ForbiddenException(); 
    } 

如果提供了正確的憑據,或者如果它們不正確,則返回禁止的異常。

當我使用另一種方法來檢查用戶是否被授權後,它總是返回false(當它應該是true)。我不確定是什麼原因造成的。

try { 
     Subject currentUser = SecurityUtils.getSubject(); 

     return SecurityUtils.getSubject().isAuthenticated(); 

    } catch (AuthenticationException e) { 
     throw new ForbiddenException(); 
    } 

currentUser在調試模式下檢查時爲空。

我也可以使用其他方法,但它會在第二行中返回nullPointerException。

try { 

     sessionFactory.getCurrentSession().getTransaction().begin(); 

     User user = userDAO.find(securityContext.getUserPrincipal().getName()); 

     if (user == null) { 
      sessionFactory.getCurrentSession().getTransaction().rollback(); 
      throw new NotFoundException(); 
     } 

     UserModel result = new UserModel(user); 

     sessionFactory.getCurrentSession().getTransaction().commit(); 

     return result; 
} 
    } catch (HibernateException e) { 
     e.printStackTrace(); 
     sessionFactory.getCurrentSession().getTransaction().rollback(); 
    } 
    return null; 

我使用shiro.ini連接到本地數據庫。
[更新]我添加了一個調試登錄過濾器,它可以在啓用時自動登錄(使用Servlet)並且它按預期工作。

我已經添加了一個URL部分,它在我使用authcBasic時有效,但當我在Shiro中使用authc時不起作用。我可以通過調用方法isAuthenticated()getCurrentUser()進行檢查。使用authcBasic返回所有正確的信息,但authc返回false/null。除非我清理Web瀏覽器,否則在使用authcBasic時我也無法註銷。方法SecurityUtils.getSubject().logout();將isAuthenticated布爾值設置爲false(當我調試時),但似乎對會話沒有任何實際影響。

# ======================= 
# Shiro INI configuration 
# ======================= 

[main] 
# Debug filter to automatically login 
debugLogin = util.DebugLoginFilter 
debugLogin.enabled = false 
debugLogin.username = ADMIN 
debugLogin.password = ADMIN 

jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm 
jdbcRealm.authenticationQuery = select password from user where username = ? 
jdbcRealm.userRolesQuery = select role from user_role INNER JOIN user ON  user_role.id = user.user_role_id where user.username = ? 

# Datasource for the jdbc realm 
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource 
ds.serverName = localhost 
ds.user = root 
ds.databaseName = database 
jdbcRealm.dataSource = $ds 

authc.usernameParam = username 
authc.passwordParam = password 
authc.failureKeyAttribute = shiroLoginFailure 

sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher 
jdbcRealm.credentialsMatcher = $sha256Matcher 

[roles] 
admin = * 

[urls] 
/= debugLogin, authcBasic 
/index.html = debugLogin, authcBasic 
/api/login = anon 
/api/login/me = authcBasic 
/api/login/logout = authcBasic 
/api/** = debugLogin, authcBasic 

我的pom.xml

<dependency> 
    <groupId>org.apache.shiro</groupId> 
    <artifactId>shiro-core</artifactId> 
    <version>1.3.2</version> 
</dependency> 
<dependency> 
    <groupId>org.apache.shiro</groupId> 
    <artifactId>shiro-web</artifactId> 
    <version>1.3.2</version> 
</dependency> 

我的web.xml

<listener> 
    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> 
</listener> 

<filter> 
    <filter-name>ShiroFilter</filter-name> 
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> 
</filter> 

<filter-mapping> 
    <filter-name>ShiroFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>REQUEST</dispatcher> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>INCLUDE</dispatcher> 
    <dispatcher>ERROR</dispatcher> 
</filter-mapping> 

道歉,如果我犯任何錯誤,我是新來的!任何幫助將不勝感激。

編輯:此消息顯示在控制檯中運行Apache服務器時:

[localhost-startStop-1] INFO org.apache.shiro.config.IniSecurityManagerFactory - Realms have been explicitly set on the SecurityManager instance - auto-setting of realms will not occur. 
+0

在你的應用程序中你調用SecurityUtils.getSubject();那是失敗的?相同的請求或其他請求?你是從過濾器還是派生的線程中調用它? – teacurran

+0

嗨@teacurran我從前端調用它(使用Angular 2)作爲POST請求傳遞用戶名和密碼到Java後端。 SecurityUtils.getSubject();當它用於登錄時(它在調試代碼時顯示所有正確的細節)時工作,但是當我從前端再次調用它以檢查用戶是否實際登錄/認證時,它不起作用。 – ToDo

+0

沒錯。所以你正在調用一個GET請求來打你的REST api服務。如何使用過濾器處理REST服務? servlet的?如果過濾器,它可能會在shiro過濾器之前被調用,這將導致它無法正常工作。 – teacurran

回答

0

我已經找到了解決辦法。問題不在於代碼,而在於我使用的方法。

我使用Angular 2作爲前端,Java Hibernate作爲後端。 Shiro無法與前端通信,因爲它位於不同的目錄中。但是,在構建角度應用程序並將dist內容複製到後端的WebContent中之後,它的工作原理應該如此。

我將使用調試登錄過濾器手動登錄時,我正在開發(然後四郎禁用它,一旦它投入生產)。

我將保持代碼片段的情況下,別人有這個問題。

+0

當我們做'currentUser.login()',在實際的系統檢查由客戶端與一個存儲在數據庫服務器端提供了'username'和'password'? –