shiro登录认证
public class ConfigShiro { public void simpleDbCOnfig(){ DefaultSecurityManager securityManager = new DefaultSecurityManager(); Realm realm = new MyRealm(); securityManager.setRealm(realm); SecurityUtils.setSecurityManager(securityManager); } }
2、代码:生成盐,存到数据库中,salt我们也存到数据库中,解密时会取出
public void saltTest(){ //所需加密的参数 即 密码 String pwd = "123"; //[盐] 一般为用户名 或 随机数 String salt = "shiro"; //加密次数 int hashIterations = 1; /*调用org.apache.shiro.crypto.hash.SimpleHash.SimpleHash(String algorithmName, Object source, Object salt, int hashIterations) * 构造方法实现盐值加密 String algorithmName 为加密算法 支持md5 base64 等*/ SimpleHash sh = new SimpleHash("md5", pwd, salt, hashIterations); //打印最终结果,或将其存入数据库 System.out.println(sh.toHex()); }
package com.amiu.shiro.chapter5; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import com.amiu.mybatisTest.autoMybatis.SqlSessionHelper; import com.amiu.shiro.db.User; import com.amiu.shiro.db.UsersDao; public class MyRealm extends AuthorizingRealm { //操作数据库的类 @Autowired RoleService roleService; @Autowired PermissionService permissionService; @Autowired UserDao userDao; //设置盐解析,这里要和生成盐的设置相同,使用MD5,解密次数1次 @Override public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { //HashedCredentialsMatcher是shiro提供的解析盐的实现类 HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); matcher.setHashAlgorithmName("md5"); matcher.setHashIterations(1); super.setCredentialsMatcher(matcher); } //处理权限的,将角色Role和权限Permission存入shiro中 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 获取当前登录对象 User user = (User) principals.getPrimaryPrincipal(); //查询拥有角色 Map<Long, Role> mapRole = roleService.findRoleByUserId(user.getId()); List<Long> roleIds = MapUtil.toListKey(mapRole); //查询角色拥有的权限 Map<Long, Permission> mapPermission = permissionService.findByRoleId(roleIds); Set<String> roles = null; Set<String> stringPermissions = null; try { //将需要的字段转换为Set格式,name是实体类Role的字段 roles = MapUtil.toSet(mapRole, "name"); stringPermissions = MapUtil.toSet(mapPermission, "name") ; } catch (Exception e) { //这里是MapUtil工具类捕捉的异常 e.printStackTrace(); } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); //将角色与权限放入SimpleAuthorizationInfo对象 authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(stringPermissions); //返回给shiro return authorizationInfo; } //处理身份验证 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken userToken = (UsernamePasswordToken) token; //获取当前需要登录的用户 String name = userToken.getUsername(); //从数据库获取是否有对应的用户 User user = userDao.selectByName(name); if(user == null){ //不存在用户 throw new UnknownAccountException(); } //从数据库中获取账户锁定信息 if(user.isIs_lock()){ //账户被锁定 throw new LockedAccountException(); } //从数据库中取出盐 String salt = user.getPassword_salt(); //从数据库中取出密码,密码是加过盐的 String password = user.getPassword(); //转换为byte类型的盐 ByteSource byteSalt = ByteSource.Util.bytes(salt); //返回对象,上面我们设置过的盐解析类:HashedCredentialsMatcher //会帮我们解析盐,然后验证密码是否匹配 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password.toCharArray(), byteSalt, getName()); return info; } @Override public String getName() { return "myRealm"; } }
@Test public void saltLogin(){ new ConfigShiro().simpleDbCOnfig(); Subject subject = SecurityUtils.getSubject(); //页面用户“li”输入的密码是明文“123” UsernamePasswordToken token = new UsernamePasswordToken("li","123"); try { subject.login(token); } catch (UnknownAccountException unknownAccountEx) { //处理无此用户 }catch(IncorrectCredentialsException wrongPasswordEx){ //处理用户名或密码不正确 }catch(LockedAccountException lockedAccountEx){ //账户被锁定 } catch ( AuthenticationException ae ) { //不期望出现的错误 error? } Assert.assertTrue(subject.isAuthenticated()); }
1、登陆测试中的: UsernamePasswordToken token = new UsernamePasswordToken("li","123"); 执行subject.login(token)后,这个token传到了MyRealm中的方法: //处理身份验证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) 这里的参数(AuthenticationToken token)即是我们的登陆用户“li”的token 2、我们自定义的Realm,我们一般选择继承shiro的AuthorizingRealm。 3、MyRealm中的返回值: SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password.toCharArray(), byteSalt, getName()); SimpleAuthenticationInfo的第一个参数我么可以放入我们想要放入才参数,如这里的对象User,我们还能存入id 或Username等等,这个参数体现在本类处理权限的方法中: //处理权限 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) 这里的参数(PrincipalCollection principals)就是我们传入的对象User,我们可以这么使用它: User User = (User) principals.getPrimaryPrincipal(); 获取User对象后我们可以去数据库中查询权限信息,并加载到shiro中
6、解析:MyRealm中的重写方法setCredentialsMatcher()
@Override public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { super.setCredentialsMatcher(credentialsMatcher); } 1、CredentialsMatcher字面意思简单理解就是[用户匹配器],作用就是匹配密码,检查 [登录密码]是否等于[数据库中查询的密码] 2、CredentialsMatcher的默认实现是SimpleCredentialsMatcher,作用是简单匹配密码, 当匹配[登录密码:123],[数据库中查询的密码:123]时,才会成功。 当匹配[登录密码:123],[数据库中加密的密码:1f45e9afefc5e28edbcbdfae08a1f7a6]时, 是不会成功的;SimpleCredentialsMatcher作用其实也就是简单判等。 上面的setCredentialsMatcher()等同于: @Override public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { SimpleCredentialsMatcher matcher = new SimpleCredentialsMatcher(); super.setCredentialsMatcher(matcher); } 3、当我们需要匹配加盐的密码时,就不能使用SimpleCredentialsMatcher了,我们一般使用 HashedCredentialsMatcher,HashedCredentialsMatcher可以匹配[登录明文密码]与[数据库加密密码] 但是我们必须为其指定匹配规则,也就是密码加密时的加密规则,HashedCredentialsMatcher将按照 此规则解密[数据库加密密码],然后再匹配[登录明文密码],如: @Override public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) { HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); matcher.setHashAlgorithmName("md5");//设置解密算法为:md5 matcher.setHashIterations(1);//设置解密次数为1次 super.setCredentialsMatcher(matcher); }
相关推荐
-
java 微信开发 常用工具类(xml传输和解析 json转换对象) java
2019-1-8
-
java分页工具类 java
2019-1-13
-
基于zxing的二维码、条码生成、解析工具类,可设置生成码颜色及二维码logo,链式调用 java
2019-1-8
-
MySQL通用性较高的分页代码 java
2019-1-13
-
GZip 压缩解压 工具类 [ GZipUtil ] java
2019-1-12
-
Ehcache 工具类 [ EhCacheUtil ] java
2019-1-12
-
Java常用日期操作方法 java
2019-1-8
-
读取a.txt和b.txt中有序的序列,合并有序序列保存成c.txt java
2019-1-13
-
Spring防止Xss配置 java
2019-1-8
-
获取客户端真实IP地址 java
2019-1-12