1、认证 登录
检验待登录的用户是否是系统合法用户,是,认证通过,不是,就拒绝
xml配置文件
<!-- MyShiroRealm bean 配置--> <bean id="myShiroRealm" class="com.hqyj.fj.realm.MyShiroRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"></property> </bean> <!-- 配置shiro核心组件 SecurityManager --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 我们自定义的认证域对象注入到SecurityManager对象中--> <property name="realm" ref="myShiroRealm" /> </bean>
pom.xml
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency>
java代码
package com.hqyj.fj.realm; import com.hqyj.fj.pojo.Role; import com.hqyj.fj.pojo.User; import com.hqyj.fj.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.Set; /* * 认证域 * 给shiro框架返回系统中用户的认证信息 * 给shiro框架返回系统中用户的授权信息 * */ public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserService userService; //给shiro框架返回系统中待认证用户的认证信息 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //使用认证令牌获取当前待登录的用户名 String username = (String)token.getPrincipal(); //在我们的系统中查询用户的认证信息 User user = userService.getOneByUsername(username); //如果用户不存在,抛出用户不存在的异常 if(user == null){ throw new UnknownAccountException(username+"不存在"); } //在shiro会话域中共享用户信息,以便业务层获取使用 Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("loginUser", user); //使用三个参数的构造方法来构造,用户名、密码、当前认证域的名称 // SimpleAuthenticationInfo info = // new SimpleAuthenticationInfo(username, user.getPassword(), getName()); ByteSource saltBytes =ByteSource.Util.bytes(user.getUsername()); SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, user.getPassword(), saltBytes,getName()); System.out.println("获取认证信息"); System.out.println(info); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //是下面关于授权的代码,可以复制下面的//doGetAuthenticationInfo方法 return null; } }
控制层controlle java代码
@RequestMapping("/login") @ResponseBody public Map<String, Object> login(String username, String password){ //检查请求参数 if(username == null || password == null){ Map<String, Object> result = new HashMap<>(); result.put("code",-9); result.put("message","请求参数错误"); return result; } //调用服务层实现业务 return userServie.login(username,password); } @RequestMapping("/logout") @ResponseBody public Map<String, Object> logout(){ //调用服务层实现业务 return userServie.logout(); }
服务层servrce java代码
@Override public Map<String, Object> login(String username, String password) { Map<String, Object> result = new HashMap<>(); //获取当前用户 Subject subject = SecurityUtils.getSubject(); //判断当前是否已经认证过 if(!subject.isAuthenticated()){ //创建一个认证令牌 UsernamePasswordToken token = new UsernamePasswordToken(username,password); //做登录 try{ subject.login(token); }catch (UnknownAccountException e){ //未知账号异常 result.put("code", -1); result.put("message",username+"用户不存在"); return result; }catch (IncorrectCredentialsException e){ //密码错误异常 result.put("code", -2); result.put("message",username+"用户密码错误"); return result; }catch (AuthenticationException e){ result.put("code",-10); result.put("message","认证失败"); return result; } } //认证通过,获取已保存在shiro session域中的用户信息 Session session = subject.getSession(); Object loginUser = session.getAttribute("loginUser"); result.put("code", 0); result.put("message",username +"认证成功"); //直接返回给控制器方法 result.put("loginUser",loginUser); return result; } @Override public Map<String, Object> logout() { //使用shiro框架获取当前用户 Subject subject = SecurityUtils.getSubject(); //使用shiro对当前用户登出 subject.logout(); Map<String, Object> result = new HashMap<>(); result.put("code", 0); result.put("message", "成功登出"); return result; }
核心代码讲解
2、授权
当已认证用户系统收收权限时,检查所具有的权限,如果有该资源的访问权限,权限通过,允许访问,反之,拒绝访问
xml代码
<!-- shiro过滤器,用于授权 --> <!-- 这里的id shiroFilter 和web.xml中配置的代理过滤器的名称一致--> <!-- 当已经认证的用户访问系统资源时,检查所具有的权限 如果有访问权限 授权通过,允许访问吧,反之,拒绝访问 web应用收权限--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 没有认证过的用户,访问受限资源时,shiro直接跳转该配置的url--> <property name="loginUrl" value="/index.jsp"></property> <!-- 已认证过但是没有访问权限的用户 访问受限资源时 shiro直接跳转到该处置的url--> <property name="unauthorizedUrl" value="/unauthorized.jsp"></property> <property name="filterChainDefinitions"> <value> <!-- 配置过滤器链 想要控制url=身份信息:anon 匿名用户 authc 认证通过用户 roles[角色名]具有某个角色的用户 permes[权限名]具有某个权限的用户--> /shiroTag=anon /index.jsp=anon /user/login=anon /shiro/mustauthc=authc /shiro/mustauthc=roles[管理员] /shiro/mustnormal=roles[普通用户] /**=authc </value> </property> </bean>
java代码
package com.hqyj.fj.realm; import com.hqyj.fj.pojo.Role; import com.hqyj.fj.pojo.User; import com.hqyj.fj.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.Set; /* * 认证域 * 给shiro框架返回系统中用户的认证信息 * 给shiro框架返回系统中用户的授权信息 * */ public class MyShiroRealm extends AuthorizingRealm { @Autowired private UserService userService; //给shiro框架返回系统中待认证用户的认证信息 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //是上面关于认证的代码,可以复制上面的 doGetAuthenticationInfo方法; return null; } //给shiro框架返回系统中的信息 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("获取授权信息"); String username=(String) principals.getPrimaryPrincipal(); System.out.println(username); //获取待授权的用户权限信息:角色信息,和权限信息 User user=userService.getOneByUsername(username); //组装一个Set<String>角色信息 Set<String> roles=new HashSet<>(); //组装一个Set<String>权限信息 Set<String> perms=new HashSet<>(); for (Role role:user.getRoles()){ roles.add(role.getName()); } //创建一个授权角色信息 SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //赋予角色权限 info.setRoles(roles); //赋予权限相关的授权信息 info.setStringPermissions(perms); return info; } }
结果
登录成功
登录失败
授权问题
3、Session
Session 可以不通过java web 的sessi对象来实现会话功能,可以使用shiro session对象实现会话领域的数据共享问题
4、加密
登录时的密码,加密
-
散列算法
MD5 SHA1 SHA256 明文-----》xxxxx32234af455将原文的关键字提取出来,生成一串看不懂的暗文信息,从暗文信息无法还原成原文,同一个原文信息转换成唯一一个暗文信息。
-
加密算法
可以加密解密的算法
通过算法进行密码加密
xml代码
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 这里配置的算法和迭代此地,和MD5Util是一致的--> <property name="hashAlgorithmName" value="MD5"></property> <property name="hashIterations" value="1000"></property> </bean> <!-- MyShiroRealm bean 配置--> <bean id="myShiroRealm" class="com.hqyj.fj.realm.MyShiroRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"></property> </bean>
java代码
package com.hqyj.fj.utils; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.util.ByteSource; /* * 使用shiro 提供的加密相关的工具类做个加密(散列算法)明文->暗文 * */ public class MD5Util { /* * password 原文 * slat 盐 * 多次使用散列算法进行加密,增加密码强度,破解难度 * 加盐:增加密码强度,破解难度 */ public static String md5Hash(String password,String salt){ ByteSource slaBytes=ByteSource.Util.bytes(salt); //SimpleHash(String algorithmName, Object source, Object salt) SimpleHash simpleHash= new SimpleHash("MD5",password,slaBytes,1000); return simpleHash.toString(); } }
测试类结果
@Test public void testMd5Hash(){ String password="123456"; String salt="zhangsan"; String hashePass= MD5Util.md5Hash(password,salt); System.out.println(hashePass); }
此时123456已经加密