Shiro框架入门

本文详细介绍了如何使用Spring Security和Shiro框架进行用户认证、基于角色和权限的授权,并探讨了Session管理和密码加密。通过XML配置和Java代码实例,展示了登录验证、授权规则及会话共享的过程。
摘要由CSDN通过智能技术生成

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已经加密

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值