Shiro安全框架案例

基于Shiro的用户认证(不包含授权)

Spring整合Shiro

shiro原理

1.1   搭建环境

1.1.1      web模块 pom.xml

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.3.2</version>
</dependency>
<!--shiro核心包-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.3.2</version>
</dependency>

1.1.2  Web.xml配置

<!-- Shiro Security filter  filter-name这个名字的值将来还会在spring中用到,本段代码原样粘贴,注意该过滤器是代理过滤器,它什么都不干,可以通过再Spring整合中配置相应的过滤器权限拦截器进行相应的过滤器拦截-->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
<!--如果设置"targetFilterLifecycle"为true,则spring来管理Filter.init()和Filter.destroy();若为false,则这两个方法失效--> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

1.1.3  Spring整合shiro  applicationContext-shiro.xml

 <description>Shiro与Spring整合</description>

    <!--安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- 引用自定义的realm -->
        <property name="realm" ref="authRealm"/>
    </bean>

    <!-- 自定义Realm域的编写 -->
    <bean id="authRealm" class="此处为自定义Realm域的全限定类名">
        <!-- 注入自定义Realm域的密码比较器 -->
        <property name="credentialsMatcher" ref="customerCredentialsMatcher" ></property>
    </bean>

    <!-- 密码比较器:密码加密和比较 -->
    <bean id="customerCredentialsMatcher" class="自定义的证书匹配器所在的全限定类名"/>

    <!-- filter-name这个名字的值来自于web.xml中filter的名字 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录页面  -->
        <property name="loginUrl" value="/login.jsp"></property>
        <!-- 登录失败后 跳转到未经授权的页面 -->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"></property>
        <!--过滤器链定义,此处为访问路径设置过滤器链-->
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤,等号后面的单词就是过滤器 -->
            <value>

<!--如果该路径的用户不包含“模块管理”权限就禁止访问--> <!-- /system/module/list.do = perms["模块管理"] userLogin.do /userLogin* = anon mylogiin.jsp /mylogin* = anon --> /index.jsp* = anon /login.jsp* = anon /login* = anon /logout* = anon /css/** = anon /img/** = anon /plugins/** = anon /make/** = anon <!-- --> /** = authc /*.* = authc </value> </property> </bean> <!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!-- 生成代理,通过代理进行控制 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true"/> </bean> <!-- 安全管理器 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <aop:aspectj-autoproxy proxy-target-class="true"/>

2.1 自定义realm

/**
 * 自定义reamlm*/
public class AuthRealm extends AuthorizingRealm {
   @Autowired
   private UserService userService;
   @Autowired
   private ModuleService moduleService;
   /**
    *  授权管理:授权
    */
   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
      return null;
   }
   /**
    *  身份认证
    *      用于验证输入的用户名密码给,登录
    */
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
      //1.获取到用户界面输入的用户名和密码
      UsernamePasswordToken upToken = (UsernamePasswordToken) authenticationToken;
      //2.获取用户出入的用户名和密码
      String username = upToken.getUsername();
      String password = new String(upToken.getPassword());
      //3.根据用户名查询用户对象
      User user = userService.findByUsername(username);
      if(user != null) {
         //第一个参数:安全数据(user对象)
         //第二个参数:密码(数据库密码)
         //第三个参数:当前调用realm域的名称(类名即可)
         SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
         return info;
      }
      return null;  //subject.login()方法的时候会抛出异常
   }
}
AuthorizingRealm抽象类中被重写的方法来源

2.2 自定义密码比较 

在spring与shiro的整合文件中已经将该类交给realm域中,所以直接重写方法doCredentialsMatch即可

/**
 * 密码比较器
 */
public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {

   /**
    * 用户密码比较
    *      1.对用户输入的密码进行加密
    *      2.比较用户输入的密码和数据库密码是否一致
    * @param token  用户界面输入的邮箱和密码
    * @param info   安全数据:用户对象user
    *
    * 111111 + 固定值(加盐)  =  xxxxxx
    */
   public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
      //1.获取用户输入的密码
      UsernamePasswordToken upToken = (UsernamePasswordToken) token;
      String loginPassword = new String(upToken.getPassword());
      String email = upToken.getUsername();
      //2.对登录密码进行加密
      //加密:使用MD5加密
      String md5Paasword = Encrypt.md5(loginPassword, email);//密码,盐

      //info.getPrincipals();//获取安全数据,用户对象
      //获取数据库密码
      String dbPassword = (String)info.getCredentials();

      //true:登录成功,false:抛出异常
      return md5Paasword.equals(dbPassword);
   }
}

 2.3 用户登录url映射

//用户登录
@RequestMapping("/login")
public String login(String username,String password) {

    //1、通过shiro框架提供的SecurityUtils工具类获取Subject
    Subject subject = SecurityUtils.getSubject();
    //2、构造用户名密码的安全对象upToken
    UsernamePasswordToken upToken = new UsernamePasswordToken(username,password);
    //3、通过Subject的login()方法将安全对象交给shiro的安全管理器SecurityManager
    subject.login(upToken);
    //4、通过shiro获取用户对象主体,保存到session
    User user = (User) subject.getPrincipal(); //获取完全对象
    session.setAttribute("user",user);
    //5、查询菜单数据
    List<Module> moduleList = moduleService.findModuleByUserid(user.getId());
    session.setAttribute("modules",moduleList);
    return "home/main";
}

 shiro学习推荐阅读》》》》》

 》》》shiro的权限管理的注解开发只需要一个注解代码

 /**
     *  RequiresPermissions:
     *      value : 权限名称(标识)
     *  如果具备此权限:进入方法
     *  不具备此权限:抛出异常
     */
    @RequiresPermissions("模块管理")
    @RequestMapping(value = "/list",name = "查询所有")
    public String list(@RequestParam(defaultValue = "1")int page,@RequestParam(defaultValue = "3")int size){
        PageInfo info = moduleService.findAll(page,size);
        request.setAttribute("page",info);
        return "system/module/module-list";
    }

2.4   页面标签展示

通过shiro标签控制页面按钮和菜单的显示

2.4.1      引入标签库

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

2.4.2      控制显示

<shiro:hasPermission name="删除部门">
    <button type="button" class="btn btn-default" title="删除" onclick='deleteById()'><i class="fa fa-trash-o"></i> 删除</button>
</shiro:hasPermission>

2.4 用户退出

//退出
    @RequestMapping(value = "/logout",name="用户登出")
    public String logout(){
        SecurityUtils.getSubject().logout();   //登出
        return "forward:login.jsp";
    }

shiro自动管理session,此处会将session中的用户信息清除。

shiro获取当前用户的用户名

Subject subject = SecurityUtils.getSubject();
Object principal = subject.getPrincipal();

 

 

点击查看SpringBoot整合Shiro

posted @ 2019-08-01 11:54  手握钢叉的猹  阅读(1093)  评论(0编辑  收藏  举报