Shiro Security

I have been using springside's open source projects as the project infrastructure. Starting from springside4, the authority management framework has been replaced by SpringSecurity with shiro. Since I have always used spring's authority management framework, this time I also made a simple comparison between shiro and SpringSecurity. If I have time, I will We will build a set of general rights management framework of maven+springboot+spring-data-jpa+hibernate/mybatis+shiro+bootstrap as a maven template and share it with you later.

The specific arrangement is as follows:

1. Permission Model

In addition to being simple enough, the difference between Shiro and SpringSecurity is that it supports two sets of APIs: permission judgment and role judgment. The code can either simply judge hasRole("administrator") or more accurately judge hasPermission("Order:Approve").

In fact, most applications use the latter. Roles are only used to organize and manage a set of permissions, and are not used for direct permission judgment in the final code (JSP, URL Filter, Java Code).

However, both SpringSecurity and JAAS only support the API based on role judgment, so in the previous code, it would be awkward to use Role as Permission ("ROLE_User:Approve").

2. User permission structure

Another difference is that the permissions of the SpringSecurity user are constructed and saved in the session when they log in. If you change the permissions of a user or role in the middle, you can only find a way to kick him off and log in again to take effect. On the other hand, Shiro will query the permissions every time the permissions are checked. Of course, for performance considerations, Shiro provides at least two permission caching solutions, as detailed in the Caching section below.

3. Permission control

Permission control is divided into three layers: page content, URL, and Java code. The old rule is that taglib is used for page content, URL control is configured in applicationContext.xml, and Java code is Annotation.

The control of page content ensures that well-meaning users will not click on functions that they do not have permission to. For malicious users, whether to perform verification at the URL or Java layer (which is divided into Controller or Service layers) can be determined according to actual needs.

In quickstart, because all JSPs have been protected under WEB-INF/ and cannot be accessed directly, all page accesses have to go through the Controller, so using Annotation for malicious user protection is better, and URL level only does Restrictions on whether the user is logged in.

Step by Step

Step1. Create a login.jsp

The default input box names should be userName, password and rememberMe.

If there is an exception in the login, it will put a requestAttribute called "shiroLoginFailure", and the content is the class name of Exception. The login.jsp in the showcase demonstrates different error messages for different exceptions.

Note that the actual login and logout operations are done by the shiroFilter configured in applicationContext.xml, so even if you write a soy sauce Controller in SpringMVC, it should only be responsible for displaying the initial login.jsp and logging in if it fails Show login.jsp again.

Step2. Implement an AuthorizingRealm

Function to find the user AuthenticationInfo, including username, password and Salt. The function for finding permissions, both Role and Permission, are called only when the CacheManager cache does not exist. Generally, passwords are not stored in plain text, and you need to specify a password matcher in the constructor. For example, the more popular one is using salt, 1024 times sha-1 hash. If you want to display more information about the current user on the page, you can construct a specific The user object, not just the user's loginName, can also contain id, display name, etc.

Step3. ShiroFilter in web.xml takes care of it all

Use Shiro filter to control / , pay attention to spring's DelegatingFilterProxy here, you need to define a bean with the same name as filter-name in applicationContext-.xml

Step4. Configuration in applicationContext-*.xml

The most important thing is the configuration of filterChainDefinitions in ShiroFilter. The configuration is from top to bottom. The top one is the most detailed explanation here:  http://shiro.apache.org/web.html#Web-defaultfilters,  applicationContext-shiro in quickstart The .xml is configured as follows:

/login = authc
/logout = logout
/static/** = anon
/** = user

authc filter listens for /login POST requests (regardless of Get) for login authentication. If it is successful, it will jump back to the previous page or the successfulUrl configured above. If it fails, it will be forwarded to the login page, but this time it is a POST, and the LoginController that uses soy sauce should pay attention.

The logout filter is responsible for monitoring /logout, so set the "logout" link to /logout

/static/** These static images do not need to be monitored, just let them go, and then the next few links need permission control.

/** = user Finally, ensure that all urls except the above urls must be logged in, and users who are not logged in will jump to the login page.

In addition, RememberMe is implemented by cookie by default, which is valid for one year. If it needs to be changed, configure a new RememberMeManager and inject it into SecurityManager.

Note that two stars are used in the URL Pattern to achieve full matching at any level

Other optional settings

/admin/** = roles[admin]
/rest/users = authcBasic

Step5. JSP content control

http://shiro.apache.org/web.html#Web-taglibrary, 提供了那些必然有的标签,如表示只有未登录才显示(显示请登录),表示只有登录了才显示(显示请退出),检查权限等等.

比较有趣是显示当前用户的标签,你可以在reaml登录时自定义一个用户对象(见step2),然后用显示下面的标签想显示的属性。

<principal property="firstName"/> 

Shiro默认没有提供hasAnyPermissions的tag,因此Springside-core中另外提供了一个增强的版本,jsp中定义taglib时,url改为http://www.springside.org.cn/tags/shiro 即可

Step6. 方法级控制

在applicationContext.xml(Service层)或spring-mvc.xml中加入AOP定义,见quickstart的spring-mvc.xml

在方法上加入

    @RequiresPermissions("User:Edit")

如果要实现多个Role之间Or的关系,可以写成这样:

    @RequiresRoles(value = { "Admin", "User" }, logical = Logical.OR)

如果要在controller上用annotation控制权限,spring-mvc.xml需要如下配置:

1.因为applicationContext-shiro.xml中的AOP管不到controller,因此需要在spring-mvc.xml中加入相同配置

2.添加统一的异常处理,用SimpleMappingExceptionResolver映射UnauthorizedException到eror/403.jsp, 因为出现此错误的用户基本都是恶意用户,因此403.jsp简单显示错误即可。

Tips

1. 各种Bean找不到的问题。

A. 与Spring Data JPA同时使用时,ShiroFilterFacotryBean的BeanPostProcessor报找不到XXDao类,可能是Spring Data JPA的BeanPostProcessor还没完成自己的任务吧。一个workaround方法是在shiroDbRealm的定义里加上depends-on="缺失Dao"的定义,强制Dao被初始化。 B. 用AOP控制方法时,把DefaultAdvisorAutoProxyCreator的proxyTargetClass属性设为true,与事务AOP一起使用cglib。

2. Cache

如前所述,Shiro会在每次鉴权时重新获取用户的授权信息,一般需要用Cache缓存起来。

默认的Cache是JVM内的,不会过期,这就需要在用户和角色管理中,显式的插入代码在修改用户/角色后清理缓存。如果懒一点,可以使用Ehcache单机版,定义120秒自然过期。另外,如果是集群,又希望即时更新,就又需要使用Ehcache 集群方案如Ehcache-RMI,又要插入代码即时更新。 但个人还是推荐使用120秒自然过期最为简单方便,见showcase中的示例。

   
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroDbRealm" />
        <property name="cacheManager" ref="shiroEhcacheManager" />
    </bean>
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:security/ehcache-shiro.xml"/>
    </bean>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326267494&siteId=291194637