博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Shiro的使用详解(干货)
阅读量:6336 次
发布时间:2019-06-22

本文共 7498 字,大约阅读时间需要 24 分钟。

小伙伴们,以下仅是干货哦(思路)

基于SSM(Spring+SpringMVC+Mybatis)框架做的思路哦

一、自定义MyRealm类

首先在使用Shiro的时候我们要考虑在什么样的环境下使用:

  • 登录的验证
  • 对指定角色的验证
  • 对URL的验证

基本上我们也就这三个需求,所以同时我们也需要三个方法:

  1. findUserByUserName(String username)根据username查询用户,之后Shiro会根据查询出来的User的密码来和提交上来的密码进行比对。
  2. findRoles(String username)根据username查询该用户的所有角色,用于角色验证
  3. findPermissions(String username)根据username查询他所拥有的权限信息,用于权限判断。

Mapper 代码

id, username, password,roleId
现在就需要创建自定义的
MyRealm类,这个还是比较重要的。继承至
Shiro
AuthorizingRealm类,用于处理自己的验证逻辑,下面贴一下我的代码:

MyRealm类

 
package com.crossoverJie.shiro;
import com.crossoverJie.pojo.T_user;
import com.crossoverJie.service.T_userService;
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 javax.annotation.Resource;
import java.util.Set;
/**
* Created with IDEA
* Created by ${jie.chen} on 2016/7/14.
* Shiro自定义域
*/
public
class MyRealm extends AuthorizingRealm {
@Resource
private T_userService t_userService;
/**
* 用于的权限的认证。
*
@param principalCollection
*
@return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = principalCollection.getPrimaryPrincipal().toString() ;
SimpleAuthorizationInfo info =
new SimpleAuthorizationInfo() ;
Set<String> roleName = t_userService.findRoles(username) ;
Set<String> permissions = t_userService.findPermissions(username) ;
info.setRoles(roleName);
info.setStringPermissions(permissions);
return info;
}
/**
* 首先执行这个登录验证
*
@param token
*
@return
*
@throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
//获取用户账号
String username = token.getPrincipal().toString() ;
T_user user = t_userService.findUserByUsername(username) ;
if (user !=
null){
//将查询到的用户账号和密码存放到 authenticationInfo用于后面的权限判断。第三个参数随便放一个就行了。
AuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),
"a") ;
return authenticationInfo ;
}
else{
return
null ;
}
}
}

二、Controller

package com.crossoverJie.controller;import com.crossoverJie.pojo.T_user;import com.crossoverJie.service.T_userService;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.subject.Subject;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;/** * Created with IDEA * Created by ${jie.chen} on 2016/7/14. * 后台Controller */@Controller@RequestMapping("/")public class T_userController {    @Resource    private T_userService t_userService ;    @RequestMapping("/loginAdmin")    public String login(T_user user, Model model){        Subject subject = SecurityUtils.getSubject() ;        UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword()) ;        try {            subject.login(token);            return "admin" ;        }catch (Exception e){            //这里将异常打印关闭是因为如果登录失败的话会自动抛异常//            e.printStackTrace();            model.addAttribute("error","用户名或密码错误") ;            return "../../login" ;        }    }    @RequestMapping("/admin")    public String admin(){        return "admin";    }    @RequestMapping("/student")    public String student(){        return "admin" ;    }    @RequestMapping("/teacher")    public String teacher(){        return "admin" ;    }}
主要就是login()方法。逻辑比较简单,只是登录验证的时候不是像之前那样直接查询数据库然后返回是否有用户了,而是调用subjectlogin()方法,就是我上面提到的,调用login()方法时Shiro会自动调用我们自定义的MyRealm类中的doGetAuthenticationInfo()方法进行验证的,验证逻辑是先根据用户名查询用户,如果查询到的话再将查询到的用户名和密码放到SimpleAuthenticationInfo对象中,Shiro会自动根据用户输入的密码和查询到的密码进行匹配,如果匹配不上就会抛出异常,匹配上之后就会执行doGetAuthorizationInfo()进行相应的权限验证。
doGetAuthorizationInfo()方法的处理逻辑也比较简单,根据用户名获取到他所拥有的角色以及权限,然后赋值到SimpleAuthorizationInfo对象中即可,Shiro就会按照我们配置的XX角色对应XX权限来进行判断,这个配置在下面的整合中会讲到。

三、整合Spring

web.xml配置

首先我们需要在web.xml进行配置Shiro的过滤器。

shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
shiroFilter
/*
配置还是比较简单的,这样会过滤所有的请求。
之后我们还需要在Spring中配置一个
shiroFilter的bean。

spring-mybatis.xml配置

/loginAdmin=anon
/admin*=authc /student=roles[teacher] /teacher=perms["user:create"]
在这里我们配置了上文中所提到的自定义myRealm,这样Shiro就可以按照我们自定义的逻辑来进行权限验证了。其余的都比较简单,看注释应该都能明白。着重讲解一下:

 
<property name="filterChainDefinitions">
<value>
<!--anon 表示匿名访问,不需要认证以及授权-->
/loginAdmin=anon
<!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
/admin*=authc
/student=roles[teacher]
/teacher=perms["user:create"]
</value>
</property>

  • /loginAdmin=anon的意思的意思是,发起/loginAdmin这个请求是不需要进行身份认证的,这个请求在这次项目中是一个登录请求,一般对于这样的请求都是不需要身份认证的。
  • /admin*=authc表示 /admin,/admin1,/admin2这样的请求都是需要进行身份认证的,不然是不能访问的。
  • /student=roles[teacher]表示访问/student请求的用户必须是teacher角色,不然是不能进行访问的。
  • /teacher=perms[“user:create”]表示访问/teacher请求是需要当前用户具有user:create权限才能进行访问的。
    更多相关权限过滤的资料可以访问shiro的官方介绍

四、使用Shiro标签库

Shiro还有着强大标签库,可以在前端帮我获取信息和做判断

 
<%--
Created
by
IntelliJ
IDEA.
User:
Administrator
Date:
2016/
7/
14
Time:
13:17
To
change
this
template
use
File |
Settings |
File
Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head>
<title>后台
</title>
</head>
<body>
<shiro:hasRole name="admin">
这是admin角色登录:
<shiro:principal>
</shiro:principal>
</shiro:hasRole>
<shiro:hasPermission name="user:create">
有user:create权限信息
</shiro:hasPermission>
<br>
登录成功
</body>
</html>

要想使用Shiro标签,只需要引入一下标签即可:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
其实英语稍微好点的童鞋应该都能看懂。下面我大概介绍下一些标签的用法:

  • 具有admin角色才会显示标签内的信息。
  • 获取用户信息。默认调用Subject.getPrincipal()获取,即 Primary Principal。
  • 用户拥有user:create这个权限才回显示标签内的信息。

再分享一个Shiro封装的MD5加密

 
package com.wang.shiro;
import org.apache.shiro.crypto.hash.Md5Hash;
/**
*
* 基于Shiro的MD5加密
*
*/
public class MD5Util {
public static String md5(String str,String salt){
return new Md5Hash(str,salt).toString() ;
}
public static void main(String[] args) {
String md5 = md5("abc123","crossoverjie") ;
System.out.println(md5);
}
}

代码非常简单,只需要调用Md5Hash(str,salt)方法即可,这里多了一个参数,第一个参数不用多解释,是需要加密的字符串。第二个参数salt中文翻译叫盐,加密的时候我们传一个字符串进去,只要这个salt不被泄露出去,那原则上加密之后是无法被解密的,在存用户密码的时候可以使用,感觉还是非常屌的。

小伙伴们试试吧  !!!!!!!!!!!!!!!!!!!

转载地址:http://ejooa.baihongyu.com/

你可能感兴趣的文章
NetBackup下ORACLE恢复测试方案实例解析
查看>>
【有奖征文】“失业”程序员的苦辣酸甜
查看>>
IE9是如何被FireFox4超越全球市场份额的?
查看>>
linux bunzip2命令
查看>>
敏捷个人:通过实践TOGAF来思考如何学习并应用新的方法?
查看>>
Android系统的开机画面显示过程分析(6)
查看>>
vivo Hi-Fi+QQ音乐 数字音乐市场的一剂良方
查看>>
Cocos2d-x 3.2 异步动态加载 -- 保卫萝卜开发总结
查看>>
聚焦触宝反侵权事件:中国创业者用什么护航海外市场大门
查看>>
AOP技术基础
查看>>
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析(2)
查看>>
无线802.11n 2.4G与5G性能测试
查看>>
子域名信息收集攻略
查看>>
[Android]开发数独游戏思路分析过程
查看>>
SpreadJS 类Excel表格控件 - V12 新特性详解
查看>>
理解并取证:IPv6与IPv4在报文结构上的区别
查看>>
EOS主网上线只是开始,如何运营决定未来
查看>>
不用Visual Studio,5分钟轻松实现一张报表
查看>>
(译)如何使用cocos2d和box2d来制作一个Breakout游戏:第一部分
查看>>
计算机图形学(一) 图形系统综述
查看>>