Spring mvc整合shiro 框架详细解析

 

一、项目的版本

Spring 全家桶-4.3.5版本

shiro版本-1.3.2 核心容器

下面是maven依赖的配置


  UTF-8
  1.7
  1.7

  
  4.3.5.RELEASE
  1.4.4.RELEASE
  
  3.2.8
  
  4.3.5.Final

  
  5.1.29

  
  



  commons-logging
  commons-logging
  1.2


  org.apache.shiro
  shiro-core
  1.3.2

  
      org.apache.shiro
      shiro-web
      1.3.2
  
  
      org.apache.shiro
      shiro-spring
      1.2.2
  

  org.apache.shiro
  shiro-ehcache
  1.3.2



  org.springframework
  spring-core
  ${spring.version}


  org.springframework
  spring-web
  ${spring.version}


  org.springframework
  spring-oxm
  ${spring.version}


  org.springframework
  spring-tx
  ${spring.version}


  org.springframework
  spring-jdbc
  ${spring.version}


  org.springframework
  spring-webmvc
  ${spring.version}


  org.springframework
  spring-context
  ${spring.version}


  org.springframework
  spring-context-support
  ${spring.version}


  org.springframework
  spring-aop
  ${spring.version}

二、配置shiro文件




    Shiro Configuration

    
    


    
    
    
        
    

    
        
        
        
        
    

    
        
        
        
        
        
        
        
        
        
            
                
                /resource/** = anon
                /images/** = anon


                
                /user/VerifyImg = anon
                /user/login = anon
                /Forum/getForum =anon
                
                /city/bbs =anon
                /city/reg =anon
                /Register= anon
                /getPhoto =anon
                
                /** = authc
            
        
    
    
    

    
    
        
    
    


    
    
        
        
        
    

    
        
        
        

    
    

三、编写shiro权限认证类

这个认证类是跟着上面的配置文件,这个拦截类是可以配置多个,每个应用的地方都可以不一样,我这里配置的主要是拦截用户的总体项目的访问权限模块。大家可以根据自己的需要创建不同的拦截类。

这里面的service类我就不贴出来了,大家可以根据自己的实际service来进行业务操作。当然有需要的可以私下留言

Spring mvc整合shiro 框架详细解析_第1张图片

import com.BBS.pojo.User;
import com.BBS.service.GeneralService;
import com.BBS.service.UserService;
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.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

/**
 * @author zhanglq
 * @version 1.0
 * @date 2019/11/15 11:34
 * @info shiro权限认证类
 */
public class AuthenticationFilter extends AuthorizingRealm {

    @Autowired
    private UserService userService;

    @Autowired
    private GeneralService generalService;

    /**
     * shiro授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 使用Shiro提供的方法获取用户名称
        User user = (User) getAvailablePrincipal(principalCollection);

        if (user != null) {
            List list = generalService.findForJdbc("select roleId  from user_role where user_id = ?",new Object[]{user.getId()});
            String roleId = (String) list.get(0);

            // 获取用户的权限
            List roleList = generalService.findForJdbc("select res_id from role_res where role_id = ?", new Object[]{roleId});

            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

            if (roleId != null) {
                info.addRole(roleId);
            }
            if (roleList != null) {
                info.addStringPermission(roleList.toString());
            }
            return info;

        }


        return null;
    }
    /**
     * shiro认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;

        String loginName = token.getUsername();
        if (loginName != null &&! "".equals(loginName)) {
            //通过登录名获取用户
            User user = userService.findByLoginName(loginName);
            if (user != null) {
                // 如果身份认证验证成功,返回一个AuthenticationInfo实现
                return new SimpleAuthenticationInfo(user.getLoginname(),user.getPassword(),user.getId());
            }
        }
        return null;
    }
}

四、接下是controller 层实现权限的认证。

上面那个类,可以使用注解的形式访问,也可以自己主动访问这个认证类,去查询相关角色用户有没有对应的权限操作。

 @RequestMapping(value = "/login", method = RequestMethod.POST)
    public ModelAndView loginPost(ModelAndView mv, RedirectAttributes redirectAttributes, HttpServletRequest request,User user) {
        String verifyCode = request.getSession().getAttribute("verifyCode").toString().toLowerCase();//获取session中的验证码  不区分大小写

        String vercode = request.getParameter("vercode").toLowerCase();//获取用户提交的验证码
        Subject currentUser = SecurityUtils.getSubject();

        //1. 接受提交的当事人的证书,以及host地址,第一参数用户名,第二个参数密码,第三个参数host,我这里传了ID:
        UsernamePasswordToken token = new UsernamePasswordToken(user.getLoginname(), user.getPassword(), user.getId());
        try {
            //用户认证
            currentUser.login(token);
        } catch (AuthenticationException e) {
            System.out.println(e.getMessage());
            redirectAttributes.addFlashAttribute("message", "用户名或密码错误!");
            mv.setViewName("bbs_jsp/user/Login");
            return mv;
        }
        if (currentUser.isAuthenticated()) {
            //登录成功,保存用户相关信息
            User session_user = this.userService.findByLoginName(user.getLoginname());
            SessionUtils.setAttr(request,AppConstant.SESSION_USER,session_user);
        
            //跳转成功页面
            mv.setViewName("bbs_jsp/index");
            mv.addObject("Forum", page);
            mv.addObject("Weeks", weeks);
            return mv;
        } else {
            redirectAttributes.addFlashAttribute("message", "用户名或密码错误!");
            mv.setViewName("bbs_jsp/user/Login");
            return mv;
        }
    }

上面那里我是主动调用的shiro 的主体类,subject去查询用户的相关权限。subject是核心,每一个用户都可以是一个subject。当然也可以用使用注解去验证

Spring mvc整合shiro 框架详细解析_第2张图片

Shiro的认证注解处理是有内定的处理顺序的,如果有个多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):

当前Subject必须拥有所有指定的角色时,才能访问被该注解标注的方法。如果当天Subject不同时拥有所有指定角色,则方法不会执行还会抛出AuthorizationException异常。

RequiresRoles 

当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法。如果当前Subject不具有这样的权限,则方法不会被执行。
RequiresPermissions 

使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证
RequiresAuthentication 

当前Subject必须是应用的用户,才能访问或调用被该注解标注的类,实例,方法。
RequiresUser 

使用该注解标注的类,实例,方法在访问或调用时,当前Subject可以是“gust”身份,不需要经过认证或者在原先的session中存在记录。
RequiresGuest

上面是的排序是执行的顺序

使用列子

//必须同时属于user和admin角色,可以填写多个
@RequiresRoles({"user","admin"})  

 //符合什么index:hello权限

@RequiresPermissions("index:hello")

下面还需要存放shiro权限的表

/**
 * @author zhanglq
 * @version 1.0
 * @date 2019/11/4 21:47
 * @idfo 角色资源权限表
 */
@Entity
@Table(name = "shiro_resource")
public class ResourceEntity extends commonEntity {


    private String resName;  //资源权限名称

    @Column(name = "res_name",length = 25)
    public String getResName() {
        return resName;
    }

    public void setResName(String resName) {
        this.resName = resName;
    }
}
/**
 * @author zhanglq
 * @version 1.0
 * @date 2019/11/4 22:07
 * @info 用户角色表
 */
@Entity
@Table(name = "role")
public class Role extends commonEntity {


    private String roleName;  // 角色名称


    @Column(name = "role_name",length = 10)
    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }
}
/**
 * @author zhanglq
 * @version 1.0
 * @date 2019/11/4 21:00
 * @info 角色-资源表,记录每个角色所有的资源权限
 */
@Entity
@Table(name = "role_res")
public class RoleResEntity extends commonEntity {


    private String roleId;   //角色id
    private String resId;   //资源权限ID

    @Column(name = "role_id",length = 5)
    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }
    @Column(name = "res_id",length = 5)
    public String getResId() {
        return resId;
    }

    public void setResId(String resId) {
        this.resId = resId;
    }
}
/**
 * @author zhanglq
 * @version 1.0
 * @date 2019/11/18 11:08
 * @info 用户角色表,记录每个用户所有的角色信息
 */
@Entity
@Table(name = "user_role")
public class UserRole  extends commonEntity {



    private String userId;  // 用户表ID
    private String roleId; //角色表ID

    @Column(name = "user_id",length = 5)
    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }
    @Column(name = "role_id",length = 5)
    public String getRoleId() {
        return roleId;
    }

    public void setRoleId(String roleId) {
        this.roleId = roleId;
    }
}

shiro的缓存参数,在shiro配置文件我配置了shiro的缓存,我查看过源码,如果我们配置了缓存类,但是没有配置参数的话。shiro他底层有一个通用参数类型,我这个是通用参数的类型。



    

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(JAVA,学习,shiro,spring,java)