发表于: 2017-08-17 17:35:30
1 1130
今天学习了如何用shiro实现登陆验证。shiro是一个十分强大的权限管理系统,和Spring和JavaWeb工程有很好的整合,所以对于一个Spring MVC项目来说,是十分理想的选择,尤其是当有许多角色需要管理时,自己去写拦截器就变得很复杂。
shiro主要可以解决验证和授权的问题,登陆就是一个验证工作,需要验证登陆的用户名和密码是否正确。
密码不管储存在什么地方,都是以暗文形式储存,即必须加过密。
shiro自带多种加密方式,例如md2,md5,sha256等,还支持加盐,加盐方式可以把随机生成的盐自定义在数据库的另一列,加强安全性。
shiro支持各种各样的储存敏感信息的方式,对于少量的用户,完全可以将用户名和密码token储存在shiro配置文件中,配置文件也可以放在远程服务器。
shiro还支持安全的使用缓存。
shiro对于敏感信息的读取,有一个自己的类叫做Realm,shiro的Realm类可以看做shiro自己的DAO,shiro为了确保安全,使用自己的Realm读取敏感信息,所以如果使用数据库储存敏感信息,必须自己实现Realm类才能使用shiro。
自己实现shiro的Realm类,可以简单的使用原生jdbc,配置单独的数据源,不需要整合dao框架。
shiro的配置有多种方式,默认通过shiro.ini文件进行全局配置,但也可以与Spring进行整合,也可以直接在web.xml文件中进行配置,但今天是第一次进行配置,所以还是选择了默认的shiro.ini文件。
shiro与Spring整合有一个不可替代的好处,就是可以直接使用注解对方法添加权限,这是普通情况下使用URL路径进行配置无法实现的,所以将来对shiro和Spring进行整合还是十分必要的。
使用shiro框架后,不需要自己配置Cookie和session,完全有shiro自己实现,默认使用的就是Web容器的Session,也可以自定义Session。
在Spring MVC项目中实现登陆,只需要配置shiro.ini,和Realm实现类,和web.xml中的一个监听器和过滤器,具体如下。
shiro.ini
[main]
myRealm = com.ptteng.carrot.yongzheng.util.AuthenticateRealm
securityManager.realm = $myRealm
sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
sha256Matcher.storedCredentialsHexEncoded = false
myRealm.credentialsMatcher = $sha256Matcher
authc.loginUrl = /login.jsp
[urls]
/login.jsp = authc
/a/** = authc
web.xml
<!--shiro过滤器-->
<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>
Realm实现类,配一个数据源(不能使用Autowire,原因可能是shiro的初始化更靠前):
public class AuthenticateRealm extends AuthenticatingRealm {
private static final Log log = LogFactory.getLog(AuthenticateRealm.class);
protected static final String AUTHENTICATION_QUERY = "SELECT password_token FROM account WHERE name = ?";
private DataSource dataSource;
public AuthenticateRealm() {
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://zengtian.cc:3306/carrot_yongzheng");
basicDataSource.setUsername("root");
basicDataSource.setPassword("root");
dataSource = basicDataSource;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
String username = userToken.getUsername();
// Null username is invalid
if (username == null) {
throw new AccountException("Null usernames are not allowed by this realm.");
}
Connection conn = null;
SimpleAuthenticationInfo info = null;
try {
conn = dataSource.getConnection();
PreparedStatement ps = null;
ps = conn.prepareStatement(AUTHENTICATION_QUERY);
ps.setString(1, username);
ResultSet rs = null;
String password = null;
rs = ps.executeQuery();
while (rs.next()) {
password = rs.getString(1);
}
if (password == null) {
throw new UnknownAccountException("No account found for user [" + username + "]");
}
info = new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
} catch (SQLException e) {
final String message = "There was a SQL error while authenticating user [" + username + "]";
log.error(message, e);
// Rethrow any SQL errors as an authentication exception
throw new AuthenticationException(message, e);
} finally {
JdbcUtils.closeConnection(conn);
}
return info;
}
//禁用shiro服务
/*@Override
public boolean supports(AuthenticationToken token) {
return false;
}*/
}
加密帮助类,用于做注册页面时使用,加密方式一定要和shiro.ini中一致,否则注册的加密和登陆的加密不一样:
public class Hasher{
public static void main(String[] args) {
Hasher hasher = new Hasher();
System.out.println(hasher.encrypt("admin"));
}
public String encrypt(String input){
//加盐
//RandomNumberGenerator rng = new SecureRandomNumberGenerator();
//Object salt = rng.nextBytes();
//String out = new Sha256Hash(input, salt, 1024).toBase64();
return new Sha256Hash(input).toBase64();
}
}
问题:登陆成功后,会自动跳转到项目根路径,找不到地方改,不能指定成功页面,除非复写过滤器的方法。
明天:解决登陆中的种种问题。
总结:无
进度:http://task.ptteng.com/zentao/project-burn-277.html
demo延期至少一周。
评论