package com.shiro.bean; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.util.ByteSource; /** * @author layne * Action方法中执行subject.login(token)时会通过IOC容器调取Realm域进行数据和前端数据比对 */ public class ShiroRealm extends AuthenticatingRealm { /** * Returns all principals associated with the corresponding Subject. Each principal is an identifying piece of * information useful to the application such as a username, or user id, a given name, etc - anything useful * to the application to identify the current <code>Subject</code>. * The returned PrincipalCollection should <em>not</em> contain any credentials used to verify principals, such * as passwords, private keys, etc. Those should be instead returned by {@link #getCredentials() getCredentials()}. * @return all principals associated with the corresponding Subject. * * doGetAuthenticationInfo,获取认证消息,如果数据库没有数据,返回null. * AuthenticationInfo可以使用 SimpleAuthenticationInfo实现类,封装给正确用户名和密码 * token参数:需要验证的token */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { /** * 1.将token转换为UsernamePasswordToken * 2.获取用户名 * 3.查询数据库,进行验证 * 4.结果返回 * 5.验证不通过,抛出异常 */ //1.将token转换为UsernamePasswordToken UsernamePasswordToken upToken = (UsernamePasswordToken)token; //2.获取用户名 String userName = upToken.getUsername(); //获取用户名后。通过查询用户名查询数据库是否有值,有值则进行密码验证。 SimpleAuthenticationInfo info=null; //3。查询数据库 //使用JDBC链接数据库进行查询 try { Class.forName("com.mysql.jdbc.Driver"); String url="jdbc:mysql://localhost:3306/test"; Connection conn=DriverManager.getConnection(url,"root",""); PreparedStatement ps = conn.prepareStatement("select * from account where name=?"); ps.setString(1, userName); ResultSet rs = ps.executeQuery(); if(rs.next()){ Object principal=userName; Object credentials=rs.getString(3); String realmName=this.getName(); //设置盐值 ByteSource salt=ByteSource.Util.bytes(userName); //SimpleHash sh=new SimpleHash(algorithmName, source, salt, iterations); // 加密类型 加密资源 盐值加密 加密次数 //给从数据库中拿到的密码做MD5的加密 SimpleHash sh=new SimpleHash("MD5", credentials, salt, 1024); //info = new SimpleAuthenticationInfo(principal, credentials, realmName); //info = new SimpleAuthenticationInfo(principal, sh, realmName); //通过关于盐值的构造器,将前端传入的密码在加密时再加入盐值 info = new SimpleAuthenticationInfo(principal, sh, salt, realmName); }else{ throw new AuthenticationException(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return info; } }