一、名词解释

网上一大堆

二、pom依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.2</version>
</dependency>

encache可选,主要用于鉴权时的缓存

三、shiroConfiguration

shiro的配置主要是shiroFilter和securityManager的设置

@Component
public class ShiroConfiguration {

@Bean
public EhCacheManager ehCacheManager()
{
EhCacheManager manager = new EhCacheManager();
manager.setCacheManagerConfigFile("classpath:ehcache-shiro.xml");
return manager;
} @Resource
private MyShiroRealm myShiroRealm;
@Bean
public SecurityManager securityManager()
{
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(myShiroRealm);
defaultWebSecurityManager.setCacheManager(ehCacheManager());
return defaultWebSecurityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
{
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> map = new LinkedHashMap<>();
Map<String,Filter> filterMap = new LinkedHashMap<>();
filterMap.put("authc",loginFilter());
filterMap.put("perms",myFilter());
shiroFilterFactoryBean.setFilters(filterMap); //map.put("/RPCAFA2A208FA648EA27C1EC30CADFC8B3D","anon");
//map.put("/**","authc");
map.put("/RPC52CA3404FDADAB18F91E8210DFCE1522","perms[admin:test]");
map.put("/RPC66EED9EBACF5FB42B9AD9C069495587F","perms[test]");
map.put("/**","authc");
//map.put("/**","myfilter");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager)
{
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/*@Bean
public MyShiroRealm myShiroRealm()
{
MyShiroRealm myShiroRealm = new MyShiroRealm();
//myShiroRealm.setCacheManager(manager);
return myShiroRealm;
}*/
@Bean
public LoginFilter loginFilter()
{
return new LoginFilter();
}
@Bean
public MyFilter myFilter()
{
return new MyFilter();
}
}

ehCahceManager是注册缓存管理器,MyShiroRealm是权限认证具体的实现,需要注册到securityManager中,shiroFilter中主要设置过滤器链。这里面我主要用到了两个过滤器,perms和authc。

perms是给访问URL设置访问权限的,比如map.put("/RPC52CA3404FDADAB18F91E8210DFCE1522","perms[admin:test]"),key是访问的URL,value是设置的权限,必须是perms[]的形式。我将需要访问的接口URL放到数据库中,在初始化配置的时候通过读取数据库将每一个需要鉴权的接口进行权限配置。authc要求必须登录认证。

由于我们是前后端分离,前端通过RPC接口访问后端服务,这块我就想当没有权限或者没有登录时,给前端返回不同的code,所以自己实现了两个filter,loginFilter替换原来的authc过滤器,myFilter替换原来的perms过滤器。

四、MyFilter和LoginFilter的实现

loginFilter继承AuthenticationFilter,myFilter继承PermissionsAuthorizationFilter

public class LoginFilter extends AuthenticationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
Subject subject = getSubject(servletRequest,servletResponse);
String path = request.getServletPath();
System.out.println("path = " + path);
if(path.equals("/RPCAFA2A208FA648EA27C1EC30CADFC8B3D"))
{
return true;
}
if(subject.getPrincipals() != null)
{
return true;
}
return false;
}
/**
* 会话超时或权限校验未通过的,统一返回401,由前端页面弹窗提示
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
throws IOException { ShiroUtil.writeResponse((HttpServletResponse) response,new Result(AuthorizationStatus.NOT_LOGIN));
    return false; }
}

首先会执行isAccessAllowed方法,我将登录的几个接口在这里进行排除,直接返回true,就是登录的接口不需要进行登录认证。当返回false时执行onAccessDenied方法,这里我直接通过响应流返回给前端json数据。

public class ShiroUtil {

    /**
* 判断是否需要认证
* @param bean
* @return true 不需要 false 需要
*/
public static boolean isContains(NotAuthorizationBean bean)
{
List<String> paths = bean.getPaths();
String name = bean.getName();
for(String path : paths)
{
if(path.equalsIgnoreCase(name))
{
return true;
}
}
return false;
} /**
* 统一返回前端json数据
* @param response
* @param data
*/
public static void writeResponse(HttpServletResponse response, Object data)
{
try {
response.setContentType("application/json");
OutputStream outputStream = response.getOutputStream();
outputStream.write(JSON.toJSONString(data).getBytes("UTF-8"));
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public enum AuthorizationStatus {
NOT_LOGIN(401,"没有登录"),
NOT_AUTHORIZATION(403,"没有授权")
; private Integer code; private String msg; AuthorizationStatus(Integer code, String msg) {
this.code = code;
this.msg = msg;
} public Integer getCode() {
return code;
} public void setCode(Integer code) {
this.code = code;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
}
}
public class Result {

    private Integer c;

    private String d;

    public Result(AuthorizationStatus status)
{
this.c = status.getCode();
this.d = status.getMsg();
} public Result(Integer c, String d) {
this.c = c;
this.d = d;
} public Integer getC() {
return c;
} public void setC(Integer c) {
this.c = c;
} public String getD() {
return d;
} public void setD(String d) {
this.d = d;
}
}

myFilter的实现类似,也是重写isAccessAllowed和onAccessDenied两个方法

public class MyFilter extends PermissionsAuthorizationFilter {
@Override
public boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws IOException {
HttpServletRequest request = (HttpServletRequest) servletRequest; String path = request.getServletPath();
System.out.println("request path = " + path);
Subject subject = getSubject(servletRequest,servletResponse);
if(path.equals("/RPCAFA2A208FA648EA27C1EC30CADFC8B3D"))
{
return true;
}
/* String[] perms = (String[])((String[])o);
boolean isPermitted = true;
if(perms != null && perms.length > 0) {
if(perms.length == 1) {
if(!subject.isPermitted(perms[0])) {
isPermitted = false;
}
} else if(!subject.isPermittedAll(perms)) {
isPermitted = false;
}
}*/ return super.isAccessAllowed(servletRequest,servletResponse,o);
}
/**
* 会话超时或权限校验未通过的,统一返回401,由前端页面弹窗提示
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response)
throws IOException {
System.out.println("no permission");
Subject subject = getSubject(request,response);
if(subject.getPrincipal() == null)
{
ShiroUtil.writeResponse((HttpServletResponse) response,new Result(AuthorizationStatus.NOT_LOGIN));
}else{
ShiroUtil.writeResponse((HttpServletResponse) response,new Result(AuthorizationStatus.NOT_AUTHORIZATION));
}
return false;
}
}

五、MyShiroRealm实现

realm是权限和登录管理的具体实现,需要继承AuthorizingRealm,实现doGetAuthorizationInfo权限认证和doGetAuthenticationInfo登录认证。

@Service
public class MyShiroRealm extends AuthorizingRealm {
@Resource
private UserInfoService userInfoService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("权限认证doGetAuthorizationInfo()");
String username = (String) super.getAvailablePrincipal(principalCollection);
System.out.println("username = " + username);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//simpleAuthorizationInfo.addRole("admin");
simpleAuthorizationInfo.addStringPermission("admin:test");
return simpleAuthorizationInfo;
} @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("登陆认证doGetAuthenticationInfo()");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
System.out.println("token = " + token.getUsername());
UserInfo userInfo = userInfoService.findByUsername(token.getUsername());
if(userInfo != null)
{
return new SimpleAuthenticationInfo(userInfo.getUsername(),userInfo.getPassword(),getName());
}
return null;
}
}

Springboot集成权限管理框架apache shiro的更多相关文章

  1. 权限框架Apache Shiro 和 Spring Security

    Shiro 首先Shiro较之 Spring Security,Shiro在保持强大功能的同时,还在简单性和灵活性方面拥有巨大优势.Shiro是一个强大而灵活的开源安全框架,能够非常清晰的处理认证.授 ...

  2. Apache Shiro 开源权限框架

    在 Web 项目中应用 Apache Shiro 开源权限框架 Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证.授权.加密.会话管理等功能.认证和授权为权限控制的核心, ...

  3. 让Apache Shiro保护你的应用

    在尝试保护你的应用时,你是否有过挫败感?是否觉得现有的Java安全解决方案难以使用,只会让你更糊涂?本文介绍的Apache Shiro,是一个不同寻常的Java安全框架,为保护应用提供了简单而强大的方 ...

  4. Apache Shiro 使用手册(三)Shiro 授权

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等. 一.授权的三要素 授权有着三 ...

  5. Apache Shiro 手册

    (一)Shiro架构介绍 一.什么是Shiro Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能: 认证 - 用户身份识别,常被称为用户"登录 ...

  6. Apache Shiro 使用手册---转载

    原文地址:http://www.360doc.com/content/12/0104/13/834950_177177202.shtml (一)Shiro架构介绍 一.什么是Shiro Apache ...

  7. Apache Shiro 使用手册

    http://kdboy.iteye.com/blog/1154644 (一)Shiro架构介绍 一.什么是Shiro  Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加 ...

  8. Apache shiro集群实现 (四)shiro授权(Authentication)--访问控制

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  9. Apache Shiro 使用手册(三)Shiro 授权(转发:http://kdboy.iteye.com/blog/1155450)

    授权即访问控制,它将判断用户在应用程序中对资源是否拥有相应的访问权限. 如,判断一个用户有查看页面的权限,编辑数据的权限,拥有某一按钮的权限,以及是否拥有打印的权限等等. 一.授权的三要素 授权有着三 ...

随机推荐

  1. RxJava 1.x 理解-1

    先看下别人实现的最基本的RxJava的实现方式: 在RxJava里面,有两个必不可少的角色:Subscriber(观察者) 和 Observable(订阅源). Subscriber(观察者) Sub ...

  2. Centos7.3 bbc tools安装

    http://blog.csdn.net/orangleliu/article/details/54099528 更新到最新 CentOS 7.3 1611 yum update -y cat /et ...

  3. Error: Top-level design entity "dff" is undefined

    原因是:在quartus库文件里面已将dff定义了,要是找使用这个名字重命名了,因而需要重新命名为其他的名字.

  4. java 的 CopyOnWriteArrayList类

    初识CopyOnWriteArrayList 第一次见到CopyOnWriteArrayList,是在研究JDBC的时候,每一个数据库的Driver都是维护在一个CopyOnWriteArrayLis ...

  5. 搭建redis集群环境

    Redis的集群机制 ============================= 转自http://lib.csdn.net/article/redis/39999 别人写的,写得不错,转了. Red ...

  6. kvm : Permission denied

    创建虚拟机类型为:“virt type :kvm” 时,会报如下错误: Could not access KVM kernel module: Permission denied failed to ...

  7. 多重采样(MultiSample)下的FBO反锯齿 【转】

    在三维渲染的过程中,锯齿总是让人讨厌的东西.抗锯齿的一种采用方式是多重采样,本文主要小记一下FBO与多重采样的关系.——ZwqXin.com 首先,关于FBO(Frame Buffer Object) ...

  8. angular 学习理解笔记

    原文:https://github.com/eoinkelly/notes/blob/master/angular/book-building-web-apps-w-angular/angular.m ...

  9. 【转载】tcp窗口滑动以及拥塞控制

    转自:http://blog.chinaunix.net/uid-26275986-id-4109679.html TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥 ...

  10. REOBJECT structure

    REOBJECT structure   包含丰富编辑控件中的OLE或图像对象的信息. Syntax 语法 typedef struct _reobject { DWORD cbStruct; LON ...