shiro+ssm框架整合+如何用session存储登录用户信息

此案例是用IDEA创建的maven的web项目



使用shiro后为什么每次必须从登陆页面进,关键在于我们在spring-shiro.xml的匿名地址和公共地址的设置。具体看下面的spring-shiro.xml中的注释



步骤一:配置pom.xml文件。直接将如下代码复制进你的pom.xml文件,要覆盖你的pom.xml文件。

框架核心步骤一




  4.0.0

  com.qf
  ssm0923
  1.0-SNAPSHOT
  war

  ssm0923 Maven Webapp
  
  http://www.example.com

  
    UTF-8
    1.7
    1.7
    5.0.8.RELEASE
  

  
    
    
      org.apache.shiro
      shiro-core
      1.2.3
    
    
      org.apache.shiro
      shiro-web
      1.2.3
    
    
      org.apache.shiro
      shiro-spring
      1.2.3
    
    
      org.apache.shiro
      shiro-ehcache
      1.2.3
    
    
      org.apache.shiro
      shiro-aspectj
      1.2.3
    
    
      org.apache.shiro
      shiro-quartz
      1.2.3
    



    
      org.apache.shiro
      shiro-ehcache
      1.2.3
    

    
      org.apache.shiro
      shiro-quartz
      1.2.3
    
    
    
      javax.servlet
      javax.servlet-api
      3.1.0
      provided
    

    
    
      mysql
      mysql-connector-java
      5.1.38
    

    
    
      org.mybatis
      mybatis
      3.2.8
    

    
    
      org.springframework
      spring-core
      ${springversion}
    

    
      org.springframework
      spring-web
      ${springversion}
    
    
      org.springframework
      spring-oxm
      ${springversion}
    
    
      org.springframework
      spring-tx
      ${springversion}
    


    
      org.springframework
      spring-jdbc
      ${springversion}
    

    
      org.springframework
      spring-webmvc
      ${springversion}
    
    
      org.springframework
      spring-aop
      ${springversion}
    

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

    
      org.springframework
      spring-test
      ${springversion}
    

    
    
    
      org.mybatis
      mybatis-spring
      1.2.2
    

    
    
      jstl
      jstl
      1.2
    

    
    
      com.alibaba
      druid
      1.0.9
    

    
    
      com.github.pagehelper
      pagehelper
      4.1.6
    
    
    
      com.fasterxml.jackson.core
      jackson-databind
      2.9.5
    
    
    
      org.apache.poi
      poi
      3.6
    
    
    
      javax
      javaee-api
      7.0
      provided
    
    
    
      commons-fileupload
      commons-fileupload
      1.3.1
    

    
      commons-io
      commons-io
      2.4
    
    
      joda-time
      joda-time
      2.9.9
    

    
      org.mybatis.generator
      mybatis-generator-core
      1.3.5
    
    
      org.slf4j
      slf4j-api
      1.7.5
    
    
      org.slf4j
      slf4j-log4j12
      1.7.12
    
    
      log4j
      log4j
      1.2.17
    
    
      org.apache.poi
      poi
      3.6
    
  

  
    ssm0923
    
      
        
          maven-clean-plugin
          3.1.0
        
        
          org.mybatis.generator
          mybatis-generator-maven-plugin
          1.3.5
          
            
            src/main/resources/generatorConfig.xml
            true
          
          
            
              org.mybatis.generator
              mybatis-generator-core
              1.3.5
            
          
        
        
        
          maven-resources-plugin
          3.0.2
        
        
          maven-compiler-plugin
          3.8.0
        
        
          maven-surefire-plugin
          2.22.1
        
        
          maven-war-plugin
          3.2.2
        
        
          maven-install-plugin
          2.5.2
        
        
          maven-deploy-plugin
          2.8.2
        
      
    
  

这当中最重要的是其中的依赖。



步骤二:在resources创建名为spring.xml的文件,将如下代码复制进该文件。

框架核心步骤二




    
    
        
        
        
        
    
    
   
    
    
        
        
    
    
    
    
    
        
      
        -->
    

    
    
        
        
    
    
    
        
    
    
   
    



   

注意其中的包路径和包的相对路径,我项目的包都是com.qf开头的,如果你想试验成功,包的框架搭建按最下面的框架图搭建。如果你理解当中的意思,可随便建。其次数据库是你肯定得根据自己情况修改的



步骤三:在entity包下创建数据库表sys_user对应的实体类SysUser,因为自定义Realm会用到

非核心步骤

package com.qf.entity;


public class SysUser {
    private String id;
    private String userCode;
    private String userName;
    private String passWord;
    private String salt;
    private int locked;



    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUserCode() {
        return userCode;
    }

    public void setUserCode(String userCode) {
        this.userCode = userCode;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }

    public int getLocked() {
        return locked;
    }

    public void setLocked(int locked) {
        this.locked = locked;
    }
}


步骤四:在util包下自定义Shiro的Realm文件。 用于如何验证用户和给用户授哪些权的

非核心步骤

package com.qf.util;

import com.qf.entity.SysUser;
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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.ArrayList;
import java.util.List;
//自定义Realm一定要继承AuthorizingRealm。自定义MyRealm作用,验证前后台用户名和密码是否一致(即认证方法部分),给认证通过的用户赋予数据库中存储的对应的权限和角色信息(即授权方法部分)
public class MyRealm extends AuthorizingRealm {
    @Override
    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //在本案例中授权这个方法几乎没用到。主要用到的是下面的认证方法。写授权是作为示范
       //创建集合添加用户对应的真实权限
        List pers=new ArrayList();
        pers.add("user:select");
        pers.add("user:delete");
        //创建向前台传递权限的SimpleAuthorizationInfo对象
        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
        //调用addStringPermissions方法将装有权限的集合作为参数赋给SimpleAuthorizationInfo对象传给前台
        simpleAuthorizationInfo.addStringPermissions(pers);//有角色还可以在这加角色
        return simpleAuthorizationInfo;
    }

    @Override
    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
      String username = (String)authenticationToken.getPrincipal();//前台传过来的用户名,用于比对和数据库的用户名
      if (username.equals("zhangsan")){//张三代表数据库中正确的用户名,这里为了例子简单,没有比对密码
          SysUser sysUser=new SysUser();// SysUser使我们在entity中创建数据库中sys_user表对应的实体类。该对象用于存储登录用户信息,传给我们重写的过滤器MyFormFilter,用于将其存储到session中
          sysUser.setUserName("张三");
          return new SimpleAuthenticationInfo(sysUser,"123","myrealm");//123位数据库中的真实密码,直接通过SimpleAuthenticationInfo对象传给调用该方法的controller层
      }
        return null;
    }
}

自定义Realm的类一定要继承AuthorizingRealm




步骤五:在util下创建MyFormFilter,用于将成功登陆的用户信息存储到session中。该类必须继承FormAuthenticationFilter类,重写它的onLoginSuccess方法即可

非核心步骤

package com.qf.util;

import com.qf.entity.SysUser;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

//写该类是为了在此处将登录成功的用户信息存储在session中。注意该类是继承FormAuthenticationFilter类重写,重写它的onLoginSuccess即shiro登录成功后的处理方法。
public class MyFormFilter extends FormAuthenticationFilter {
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        //得到认证通过的主体,获取自定义的Realm中SimpleAuthenticationInfo对象传的用户信息,通过getPrincipal获取
        SysUser user=(SysUser)subject.getPrincipal();//获取自定义realm(即本案例的MyRealm)中SimpleAuthenticationInfo存储的用户名。获取密码是subject.getCredentials()
        //然后将获取到的信息存储到Session中
        HttpServletRequest httpServletRequest= WebUtils.toHttp(request);//将ServletRequest 转化成HttpServletRequest,ServletRequest似乎是HttpServletRequest的父类
        HttpSession session = httpServletRequest.getSession();//获取session对象
        session.setAttribute("user1",user);
        return super.onLoginSuccess(token, subject, request, response);
    }
}

文件的名字即MyFormFilter这个类名时随便取的但相应的位置一定要一致。




步骤五:在resources下创建spring-shiro.xml。声明自定义的一些shiro要用到的bean对象。告诉shiro我们自定义的东西的存在。

框架核心步骤三






    


    
    
    
    
        
    
     
    
        
        
        
        
        
            
            
                /favicon.ico=anon 
                /loginout=logout
             
                /**=authc

            
        

        
        
            
                
            
        
    
    
    
        
        
    



步骤六:上面就已经搭建完shiro+ssm的整合框架了,可以开始在执行类中测试了

在controller层创建名为UserController的类执行本次测试

package com.qf.controller;


import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;


//登录
@Controller
public class UserController {
    @RequestMapping("/tologin")
    public String login(HttpServletRequest request) throws Exception {
        //shiro+ssm框架中会处理成功的情况,我们在登录请求中之用处理用户名和密码比对失败的情况
        //从FormAuthenticationFilter中获取认证失败的错误信息。因为shiro比对用户名和密码不一致,返回的不是false,而是异常,因此需要我们在处理失败的情况时捕获该异常,然后进行处理
        String failure = (String) request.getAttribute("shiroLoginFailure");//shiroLoginFailure是shiro底层捕获比对错误的属性
        if (failure!=null){//failure!=null意味着shiro底层比对failure产生了值,也就是发生了错误
            if (UnknownAccountException.class.getName().equals(failure)){//shiro中前台和数据库用户名不一致,就是报UnknownAccountException异常
                throw new Exception("用户名错误");
            }else if (IncorrectCredentialsException.class.getName().equals(failure)){//shiro中前台和数据库密码不一致,就是报IncorrectCredentialsException异常
                throw  new Exception("密码错误");
            }else {
                throw new Exception("未知错误");
            }
        }
        //没发生错,就跳转登录页面
return "login";//注意这里原本应该是return "/login.jsp",但因为我们在spring.xml文件中的第三步声明了前后缀,所以才写return "login"。
    }

 /*   //退出。因为shiro自带的退出功能即 /loginout=logout。所以这几行代码就被注释了。不需要我们写处理退出请求的方法
    @RequestMapping("/loginout")
    public String out(HttpSession session){
        System.out.println("----loginout");
        session.invalidate();//使存储的session失效,清除session中的信息
        return "redirect:/login.jsp";//注意这里跳转和上面return "login"跳转页面时的区别。return "login"是转发的跳转方式,转发是SSM默认的跳转方式。 return "redirect:/login.jsp"是重定向的跳转。即使在spring.xml文件中声明了前后缀,重定向依然要写全名。
    }*/


}

执行类配套的页面跳转页面:以下三个页面一定要创建在webapp文件夹下

第一个登录的Jsp页面:命名为login.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/9/23
  Time: 14:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


login.jsp

<%--action的值是代表将表单信息发去controller层的那个方法进行处理--%> <%--在项目运行成功后,登录时记得我们在自定义Realm中假设的用户名叫zhangsan,密码是123--%> username:
<%--用了shiro后这个用户名由于并不用我们来验证而是由shiro框架来接收并验证,而它底层接收用户名的属性名就是username,因此输入用户名的控件的name属性值必须等于username,要么重写shiro当中的FormAuthenticationFilter类,重新定义username这个属性--%> password:
<%--用了shiro后这个密码由于并不用我们来验证而是由shiro框架来接收并验证,而它底层接收用户名的属性名就是password,因此输入用户名的控件的name属性值必须等于password,要么重写shiro当中的FormAuthenticationFilter类,重新定义username这个属性--%>

第二个首页的Jsp页面:命名为index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


index.jsp

当前用户:${sessionScope.user1.userName}

退出

第三个错误页面:命名为error.jsp,可不写该页面,因为这是我试验时用的,但防止上面代码牵涉到了,仍写出来了

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2019/9/25
  Time: 10:08
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    Title


   

权限不足






这是我本次案例的框架图
shiro+ssm框架整合+如何用session存储登录用户信息_第1张图片

你可能感兴趣的:(shiro+ssm框架整合+如何用session存储登录用户信息)