一、名词解释

网上一大堆

二、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. Radius报文解析(转)

    RADIUS ,是远程认证拨号用户服务的简称.RADIUS原先设计的目的是为拨号用户进行认证和计费.后来经过多次改进,形成了一项通用的认证计费协议,主要完成在网络接入设备和认证服务器之间承载认证.授权 ...

  2. Spring学习——DI(依赖注入)

    IOC容器,处理对象依赖关系 IOC与DI: IOC :是一个容器,创建对象的容器 DI :在容器创建对象后,处理对象的依赖关系,也叫依赖注入! 方式1:通过set方法注入值 可以给普通属性.集合属性 ...

  3. 如何用JavaScript重定向到另一个网页?

    可以使用 window.location.replace() 方法重定向到另一个页面.相对于 window.location.href ,replace的优势是不会跳转记录并不会保留在历史会话中,这就 ...

  4. YS端对端之间SSL通信安全问题

    1.简介:          传统的互联网,SSL通信主要基于客户端和服务器之间,在物联网时代,端和端之间的加密通信将变得很普遍,在YS业务中主要的端和端通信为: (1).客户端(移动APP,YS工作 ...

  5. Asp.net Core学习文章

    杜现鹏的Asp.net Core文章 EF Core 官方教程 https://docs.microsoft.com/en-us/ef/core/get-started/aspnetcore/new- ...

  6. WebApi单元测试记录

    一.MessageHandler不一定是全局的,也可以只应用到指定的Router上 .定义一个handler // Pipelines HttpMessageHandler affiliateShip ...

  7. ajax回调中window.open弹出的窗口会被浏览器拦截的解决方法

    存在问题:处理页面ajax请求过程中,异步请求成功后需要新开窗口打开 url,使用的是 window.open() 方法 来实现,最终都被浏览器拦截了.不会跳到对应的页面,如下 原因:浏览器之所以拦截 ...

  8. WebLogic Server 12.1.2后的字符型安装模式

    weblogic Server 12.1.1全部都可以用原来方式. WebLogic Server 12.1.2后已经取消了console安装模式,目前只有gui和静默安装模式.并且安装方式下也有很大 ...

  9. DWZ(一):框架初了解

    DWZ富client框架(jQuery RIAframework),是中国人自己开发的基于jQuery实现的Ajax RIA开源框架. DWZ富client框架设计目标是简单有用.扩展方便.高速开发. ...

  10. iOS:实现图片的无限轮播

    为尊重原创,特注明原文链接:http://m.myexception.cn/operating-system/1949043.html 图片轮播及其无限循环效果 平时APP中的广告位或者滚动的新闻图片 ...