极简方式集成Shiro

一、添加一个Shiro拦截器

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.LogKit;
import org.apache.shiro.aop.MethodInvocation;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor;

import java.lang.reflect.Method;

/**
 * Shiro 拦截器
 */
public class ShiroInterceptor extends AnnotationsAuthorizingMethodInterceptor implements Interceptor {

    public ShiroInterceptor() {
        getMethodInterceptors();    //用来扩展其他注解
    }

    @Override
    public void intercept(final Invocation inv) {
        try {
            invoke(new MethodInvocation() {
                @Override
                public Object proceed() throws Throwable {
                    inv.invoke();
                    return inv.getReturnValue();
                }
                @Override
                public Method getMethod() {
                    return inv.getMethod();
                }

                @Override
                public Object[] getArguments() {
                    return inv.getArgs();
                }

                @Override
                public Object getThis() {
                    return inv.getController();
                }
            });
        } catch (Throwable e) {
            if (e instanceof AuthorizationException) {
                doProcessuUnauthorization(inv.getController());
            }
            LogKit.warn("权限错误:", e);
        }
    }

    /**
     * 未授权处理
     *
     * @param controller controller
     */
    private void doProcessuUnauthorization(Controller controller) {
        controller.renderError(401);
    }
}

二、依赖包

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-web</artifactId>
    <version>1.3.2</version>
</dependency>

三、Config中添加拦截器配置

me.add(new ShiroInterceptor());

四、web.xml配置filter

<filter>
    <filter-name>shiro</filter-name>
    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>shiro</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

五、shiro.ini配置

例如:

[main]
sessionIdCookie = org.apache.shiro.web.servlet.SimpleCookie
sessionIdCookie.name = JFIANL_SHIRO
sessionIdCookie.path = /
sessionIdCookie.maxAge = 1800
sessionIdCookie.httpOnly = true

#jdbcRealm
##数据源
dataSource = 
dataSource.driverClassName = 
dataSource.url = 
dataSource.username = 
dataSource.password = 
dataSource.filters = 
##加密方式
credentialsMatcher = 
credentialsMatcher.hashAlgorithmName = 
credentialsMatcher.hashSalted = 
##认证方式
jdbcRealm = 
jdbcRealm.credentialsMatcher = $credentialsMatcher
jdbcRealm.dataSource = $dataSource
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.authenticationQuery = 
jdbcRealm.userRolesQuery = 
jdbcRealm.permissionsQuery = 

securityManager.realms = $jdbcRealm
#缓存实现
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager

[urls]
/** = anon


realm 具体根据项目实际情况进行调整。

六、权限控制

通过“RequiresAuthentication”、“RequiresGuest”、“RequiresPermissions”、“RequiresRoles”、“RequiresUser” 几个注解在 Controller 上进行配置:

例如:

@RequiresAuthentication
public class DashboardController extends Controller {
@RequiresPermissions("报表权限")
public void index() {
    render("/report/index.html");
}

七、模板指令扩展

参照Jboot的指令拓展,加入 Engine

http://git.oschina.net/fuhai/jboot/tree/master/src/main/java/io/jboot/component/shiro/directives

评论区

l745230

2017-09-17 19:27

集成看起来倒是简单,不过是不是也讲一下Requires这几个注解的用法呢?

toni

2017-09-17 20:54

@l745230 这个是 Shiro基础知识了和框架集成本身无关。

JFinal

2017-09-17 22:43

目前为止最简洁、最优雅的整合方案,点赞收藏

穿越123

2017-09-18 15:37

支持多个relam认证吗

djs19960601

2017-09-19 09:07

我也想问,支持多relam认证么,系统登录方式很多种

海哥

2017-10-10 11:47

赞!!!

欲风217

2017-11-22 11:03

赞!!!

lyh061619

2017-11-24 14:34

的确极简,不用启动插件,也不用注入路由

玛雅牛

2018-03-04 12:57

确实是目前最简单的整合方案,我之前写的shiro插件的好处只剩下权限计算在启动时算好,运行时性能会更好一些。 支持多个relam的话,需要自己继承AuthorizingRealm,实现自己的认证逻辑。

pingyq_wx

2018-04-09 15:40

整合的不错,但是catch代码块异常处理上面可以改改

pingyq_wx

2018-04-09 16:05

整合的极简,但是异常处理代码可以改一下

没牙的小朋友

2019-06-25 11:08

采用这种方式整合,我在action中使用renderError(404),也显示的是500错误异常信息

没牙的小朋友

2019-06-25 11:18

我将intercept方法修改成如下:
@Override
public void intercept(final Invocation inv) {
try {
invoke(new MyMethodInvocation(inv));
} catch (UnauthorizedException e) {
doProcessUnauthorization(inv.getController());
} catch (UnauthenticatedException e) {
doProcessUnauthenticatedException(inv.getController());
} catch (Throwable e) {
if (e instanceof ActionException) {
ActionException ae = (ActionException) e;
inv.getController().render(ae.getErrorRender());
} else {
throw new RuntimeException(e);
}
}
}

yuwen01

2021-03-07 11:04

服务器启动要改成jetty,undertow不支持shiro