回答
下載並安裝
下載的Apache四郎:http://shiro.apache.org/download.html; 我用Shrio - 所有(1.2.2二進制分發)http://tweedo.com/mirror/apache/shiro/1.2.2/shiro-root-1.2.2-source-release.zip
下載後在您的lib文件夾四郎,全1.2.2.jar。
我們還可以包含其他需要的.jar文件。
- MySQL驅動:http://www.java2s.com/Code/Jar/c/Downloadcommysqljdbc515jar.htm(com.mysql.jdbc_5.1.5.jar)
- SLF4J日誌記錄:http://www.slf4j.org/download.html(SLF4J-API-1.7.5.jar,SLF4J-簡單1.7.5.jar)
- 阿帕奇百科全書的BeanUtils:http://repo2.maven.org/maven2/commons-beanutils/commons-beanutils/1.7.0/(公地的BeanUtils-1.7.0.jar)
不要忘了你的罐子添加到您的構建路徑。
的web.xml
添加到您的web.xml
<!-- Apache Shero -->
<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>
<!-- Make sure any request you want accessible to Shiro is filtered. /* catches all -->
<!-- requests. Usually this filter mapping is defined first (before all others) to -->
<!-- ensure that Shiro works in subsequent filters in the filter chain: -->
<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>
shiro.ini
把你shiro.ini到WEB-INF:
[main]
authc.loginUrl = /Login.html?gwt.codesvr=127.0.0.1:9997
authc.successUrl = /Leitfaden.html
logout.redirectUrl = /login.html
# ------------------------
# Database
# Own Realm
jdbcRealm = leitfaden.login.server.MyRealm
# Sha256
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
# base64 encoding, not hex in this example:
sha256Matcher.storedCredentialsHexEncoded = false
sha256Matcher.hashIterations = 1024
jdbcRealm.credentialsMatcher = $sha256Matcher
# User Query
# default is "select password from users where username = ?"
jdbcRealm.authenticationQuery = SELECT password, salt FROM USER WHERE email = ?
# Connection
ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = localhost
ds.user = root
ds.password = root
ds.databaseName = leitfaden
jdbcRealm.dataSource=$ds
authc.usernameParam = email
authc.passwordParam = password
authc.failureKeyAttribute = shiroLoginFailure
# Use Built-in Chache Manager
builtInCacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $builtInCacheManager
# -----------------------------------------------------------------------------
[urls]
/yourMainUrl.html = authc
GWT模塊
創建一個登錄模塊。模塊名「登錄」和包名「leitfaden.login」:
添加到您的web.xml
<servlet>
<servlet-name>LoginService</servlet-name>
<servlet-class>leitfaden.login.server.LoginServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginService</servlet-name>
<url-pattern>/leitfaden.login.Login/LoginService</url-pattern>
</servlet-mapping>
LoginService.java
@RemoteServiceRelativePath("LoginService")
public interface LoginService extends RemoteService {
public Boolean isLoggedIn();
public Boolean tryLogin(String email, String password, Boolean rememberMe);
public void logout();
public void registrate(String email, String password);
}
LoginServiceAsync.java
public interface LoginServiceAsync {
public void isLoggedIn(AsyncCallback<Boolean> callback);
public void tryLogin(String email, String password, Boolean rememberMe, AsyncCallback<Boolean> callback);
public void logout(AsyncCallback<Void> callback);
public void registrate(String email, String password, AsyncCallback<Void> callback);
}
LoginServiceImpl
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService {
private static final long serialVersionUID = -4051026136441981243L;
private static final transient Logger log = LoggerFactory
.getLogger(LoginServiceImpl.class);
private org.apache.shiro.subject.Subject currentUser;
public LoginServiceImpl() {
Factory<SecurityManager> factory = new IniSecurityManagerFactory();
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
}
@Override
public Boolean isLoggedIn() {
currentUser = SecurityUtils.getSubject();
if (currentUser.isAuthenticated()) {
return true;
} else {
return false;
}
}
@Override
public Boolean tryLogin(String username, String password, Boolean rememberMe) {
// get the currently executing user:
currentUser = SecurityUtils.getSubject();
// let's login the current user so we can check against roles and
// permissions:
if (!currentUser.isAuthenticated()) {
//collect user principals and credentials in a gui specific manner
//such as username/password html form, X509 certificate, OpenID, etc.
//We'll use the username/password example here since it is the most common.
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
//this is all you have to do to support 'remember me' (no config - built in!):
token.setRememberMe(rememberMe);
try {
currentUser.login(token);
log.info("User [" + currentUser.getPrincipal().toString() + "] logged in successfully.");
return true;
} catch (UnknownAccountException uae) {
log.info("There is no user with username of "
+ token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info("Password for account " + token.getPrincipal()
+ " was incorrect!");
} catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal()
+ " is locked. "
+ "Please contact your administrator to unlock it.");
} catch (AuthenticationException ae) {
log.error(ae.getLocalizedMessage());
}
}
return false;
}
@Override
public void logout() {
currentUser = SecurityUtils.getSubject();
currentUser.logout();
}
@Override
public void registrate(String email, String plainTextPassword) {
RandomNumberGenerator rng = new SecureRandomNumberGenerator();
Object salt = rng.nextBytes();
// Now hash the plain-text password with the random salt and multiple
// iterations and then Base64-encode the value (requires less space than Hex):
String hashedPasswordBase64 = new Sha256Hash(plainTextPassword, salt,1024).toBase64();
User user = new User(email, hashedPasswordBase64, salt.toString(), 0);
this.createUser(user);
}
private void createUser(User user) {
UserDAL.connect();
UserDAL.beginTransaction();
new UserDAL().createUser(user);
log.info("User with email:" + user.getEmail() + " hashedPassword:"+ user.getPassword() + " salt:" + user.getSalt());
UserDAL.commitTransaction();
UserDAL.disconnect();
}
}
MyRealm.java
,用戶可以通過這個應用程序註冊。但是Shiro不知道如何比較醃製密碼和給定的用戶輸入。爲此,我們需要實現我們自己的領域。一個領域本質上是一個安全特定的DAO。
MyRealm。java通過給定的電子郵件獲取用戶並返回一個SaltedAuthenticationInfo。通過SaltedAuthenticationInfo Shiro知道如何將用戶輸入與數據庫中的用戶進行比較。
public class MyRealm extends JdbcRealm {
private static final Logger log = LoggerFactory.getLogger(MyRealm.class);
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// identify account to log to
UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
final String username = userPassToken.getUsername();
if (username == null) {
log.debug("Username is null.");
return null;
}
// read password hash and salt from db
final PasswdSalt passwdSalt = getPasswordForUser(username);
if (passwdSalt == null) {
log.debug("No account found for user [" + username + "]");
return null;
}
// return salted credentials
SaltedAuthenticationInfo info = new MySaltedAuthentificationInfo(username, passwdSalt.password, passwdSalt.salt);
return info;
}
private PasswdSalt getPasswordForUser(String username) {
User user = getUserByEmail(username);
if (user == null) {
return null;
}
return new PasswdSalt(user.getPassword(), user.getSalt());
}
private User getUserByEmail(String email) {
UserDAL.connect();
User user = new UserDAL().getUserByEmail(email);
UserDAL.disconnect();
return user;
}
class PasswdSalt {
public String password;
public String salt;
public PasswdSalt(String password, String salt) {
super();
this.password = password;
this.salt = salt;
}
}
}
MySaltedAuthentificationInfo 重要的是你在getCredentialsSalt()正確解碼的鹽。我已經使用Base64編碼。
public class MySaltedAuthentificationInfo implements SaltedAuthenticationInfo {
private static final long serialVersionUID = -2342452442602696063L;
private String username;
private String password;
private String salt;
public MySaltedAuthentificationInfo(String username, String password, String salt) {
this.username = username;
this.password = password;
this.salt = salt;
}
@Override
public PrincipalCollection getPrincipals() {
PrincipalCollection coll = new SimplePrincipalCollection(username, username);
return coll;
}
@Override
public Object getCredentials() {
return password;
}
@Override
public ByteSource getCredentialsSalt() {
return new SimpleByteSource(Base64.decode(salt));
}
}
用戶現在可以註冊並登錄。您只需在您的登錄模塊中調用LoginService的代碼視圖。
它是否考慮到salt是一個二進制字符串並且可以包含'\ 0'字符?特別是在數據庫中存儲可能是一個問題,但我不能判斷這一點。 – martinstoeckli
我還沒有想過這件事。但我在數據庫中存儲沒有問題。在MySQL中它工作正常。 –
- 1. 驗證鹽漬散列
- 2. 鹽漬散列算法
- 3. 鍵控或鹽漬散列?
- 4. 如何比較密碼與鹽漬散列密碼
- 5. 使用Linq To SQL鹽漬和散列密碼
- 6. 如何在數據庫中存儲鹽漬散列密碼
- 7. 鹽的位置,鹽漬
- 8. PHP檢查散列/鹽漬密碼時的登錄問題
- 9. 提取/解密散列/鹽漬密碼了XML文件的
- 10. 硬編碼密碼應該被鹽漬/散列?
- 11. 通過Java訪問GPU進行鹽漬散列
- 12. 鹽漬密碼哈希不保存鹽
- 13. 如何加鹽和散列密碼
- 14. 鹽漬的密碼安全
- 15. PBKDF2鹽醃和散列
- 16. 傳統的應用與MD5散列:如何添加鹽和SHA1?
- 17. 使用Impala查詢鹽漬Hbase rowkey
- 18. 鹽漬密碼安全
- 19. apache shiro使用散列憑證無法成功登錄
- 20. 如何從數據庫庫存和使用shiro的鹽
- 21. 如何用隨機鹽散列密碼?
- 22. 哈希和鹽漬密碼字段
- 23. Apache-Shiro和Chrome
- 24. Apache Shiro和SSO
- 25. Apache Shiro與Spring Security
- 26. 使用節點bcrypt和Passport.JS檢索鹽漬PW
- 27. 使用Cookies和鹽漬哈希的PHP登錄系統
- 28. 使用哈希作爲鹽的散列?
- 29. 我應該如何將我的sha512鹽漬和散列密碼存儲在MySQL中?
- 30. 配置Apache Shiro與Neo4j配合使用
既然是什麼地方提交教程? – koma
我做了很多研究,我花了很長時間才弄清楚shiro如何與gwt搭配使用。鹹味密碼也是一樣。我沒有在互聯網上找到類似我的教程。所以我想我想分享我的知識。這就是stackoverflow的全部內容。不是嗎? –
最好把你的公告改成一個問題(然後你自己回答)。正如已經提到的那樣,SO不是轉儲關於您的開發旅程的教程或博客的地方。 – Veger