Java---Shiro Framework

Chapter 1 Getting Started Overview

1.1 What is shiro

        Apache Shiro is a powerful and easy-to-use Java security (permissions) framework. Shiro can complete: authentication, authorization, encryption, session management, integration with the Web, caching, etc. With Shiro you can quickly and easily protect any application - from the smallest mobile app to the largest web and enterprise applications.

 1.2 Why use shiro

        The framework landscape has changed considerably since 2003, so there are still many systems using Shiro today. This is inseparable from the characteristics of Shiro.

        Ease of use: Building a system security framework with Shiro is very simple. Even if it’s your first time, you can master it quickly.

        Comprehensive: Shiro includes the functions required by the system security framework and is a "one-stop service" to meet security needs.

        Flexible: Shiro can work in any application environment. Although it can work in Web, EJB and IOC environments, there is no need to rely on them. Shiro also doesn't enforce any specifications or even many dependencies.

        Strong Web support: Shiro has excellent Web application support, can create flexible security policies based on application URLs and Web protocols (such as REST), and also provides a set of JSP libraries to control page output.

        Strong compatibility: Shiro’s design patterns make it easy to integrate with other frameworks and applications. Shiro integrates seamlessly with frameworks such as Spring, Grails, Wicket, Tapestry, Mule, Apache Camel, Vaadin and more.

1.3 Comparison between Shiro and SpringSecurity

1. Spring Security is developed based on Spring. If the project uses Spring as the basis, it is more convenient to cooperate with SpringSecurity to set permissions, but Shiro needs to be integrated with Spring for development;

2. Spring Security has richer functions than Shiro, such as security maintenance;

3. Spring Security community resources are relatively richer than Shiro;

4. Shiro is relatively simple to configure and use, but Spring Security is more complicated to get started with;

5. Shiro has low dependencies and does not require any frameworks or containers. It can run Spring Security independently and relies on Spring containers;

6. Shiro can not only be used in the web, it can work in any application environment. Perhaps one of the most important benefits of Shiro when it comes to clustering sessions is that its sessions are container independent.

1.4 What functions are there?


(1) Authentication: Identity authentication/login, verify whether the user has the corresponding identity.

(2) Authorization: Authorization, that is, permission verification, to verify whether an authenticated user has a certain permission; that is, to determine whether the user can perform any operations, such as verifying whether a user has a certain role. Or fine-grained verification of whether a user has a certain permission on a certain resource.

(3) Session Management: Session management means that after a user logs in, it is a session. Before exiting, all its information is in the session; the session can be in a normal JavaSE environment or a Web environment.

(4) Cryptography: Encryption to protect the security of data, such as passwords being encrypted and stored in the database instead of being stored in clear text.

(5) Web Support: Web support can be easily integrated into the Web environment.

(6) Caching: For example, after a user logs in, his user information and roles/permissions do not need to be checked every time, which can improve efficiency.

(7) Concurrency: Shiro supports concurrent verification of multi-threaded applications, that is, if you start another thread in one thread, the permissions can be automatically propagated.

(8) Testing: Provide testing support.

(9) "Run As": Allows one user to pretend to be another user (if they allow it).

(10) Remember Me: Remember me, this is a very common function, that is, after logging in once, you don’t need to log in next time.

1.5 Shiro architecture (external)

image-20200729114702566

Looking at Shiro from the outside, that is, looking at how to use Shiro to get things done from an application perspective

Subject: The object that application code directly interacts with is Subject, which means that the core of Shiro's external API is Subject. Subject represents the current "user", which is not necessarily a specific person. Anything that interacts with the current application is a Subject, such as web crawlers, robots, etc.; all interactions with the Subject will be delegated to the SecurityManager; the Subject is actually a Facade, SecurityManager is the actual executor

SecurityManager: Security manager; that is, all security-related operations will interact with SecurityManager; and it manages all Subjects; it can be seen that it is the core of Shiro, and it is responsible for interacting with other components of Shiro. It is equivalent to the DispatcherServlet in SpringMVC character of

Realm: Shiro obtains security data (such as users, roles, permissions) from Realm. That is to say, if SecurityManager wants to verify the user's identity, it needs to obtain the corresponding user from Realm for comparison to determine whether the user's identity is legitimate; it also needs to obtain the user's response from Realm. Use the role/permission to verify whether the user can perform operations; Realm can be regarded as a DataSource.

1.6 Shiro architecture (internal)

image-20200729114720578

  • Subject: Any "user" who can interact with the application.
  • SecurityManager: Equivalent to the DispatcherServlet in SpringMVC; it is the heart of Shiro; all specific interactions are controlled through SecurityManager; it manages all Subjects and is responsible for authentication, authorization, session and cache management.
  • Authenticator: Responsible for Subject authentication, it is an extension point and can be customized; you can use the authentication strategy (Authentication Strategy), that is, under what circumstances is the user authentication passed?
  • Authorizer: Authorizer, that is, access controller, used to determine whether the subject has permission to perform corresponding operations; that is, it controls which functions in the application the user can access.
  • Realm: There can be one or more Realm, which can be considered as a secure entity data source, that is, used to obtain secure entities; it can be a JDBC implementation, a memory implementation, etc.; provided by the user; so it is generally used in applications. You need to implement your own Realm.
  • SessionManager: A component that manages the Session life cycle; Shiro can be used not only in the Web environment, but also in ordinary JavaSE environments.
  • CacheManager: Cache controller to manage caches such as users, roles, permissions, etc.; because these data rarely change, placing them in the cache can improve access performance.
  • Cryptography: cryptography module, Shiro improves some common encryption components for password encryption/decryption.

Chapter 2 shiro login authentication

1.Create database
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0 ;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`uid` int ( 11 ) NOT NULL AUTO_INCREMENT,
`uname` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`pwd` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`sex` varchar ( 2 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,
`address` varchar ( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT
NULL ,
`state` int ( 2 ) DEFAULT NULL ,
`salt` varchar ( 32 ) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL ,
PRIMARY KEY (`uid`) USING BTREE,
UNIQUE INDEX `uname`(`uname`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE =
utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ( 1 , 'admin' , '727d8b2b4c59366d7ace58d4eda4cfee' , ' ' ,
' Luoyang, Henan ' , 1 , '9C2AB20283F9450389330033D64686DD' );
INSERT INTO `user` VALUES ( 2 , 'zs' , '83f12ba7c4357b87167e240a22c15248' , ' man ' , ' kawa
South Zhengzhou ' , 1 , '262F995823C94D1CAE7596B47E8AB657' );
select * from user
2. Create a web project and configure SSM
Complete the writing of the dao layer and service layer of the user table
3. Create MyShiroRealm and inherit AuthorizingRealm
Note: Use @Component annotation to spring management
package com.chen.shiro;
import com.chen.bean.User;
import com.chen.service.IUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
4.在spring.xml中配置shiro管理器和自定义的Realm
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* token 里面是客户端发来的信息(包含输入的用户名 和 密码)
* 自定义Realm,通过mybatis查询数据库的密码和盐值,让shiro进行身份验证
*/
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
IUserService userService;
//shiro 进行授权操作
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
principals) {
return null;
}
//shiro 进行认证操作
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken
token) throws AuthenticationException {
//token 是主体传过来的身份令牌
//1 获取用户身份信息
String uname = token.getPrincipal().toString();
//2 调用业务层获取用户信息(数据库中)
User user = userService.findByUname(uname);
//3 判断并将数据完成封装
if(user!=null){
AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
token.getPrincipal(), //令牌身份信息对象
user.getPwd(), //用户数据库的密码
ByteSource.Util.bytes(user.getSalt().getBytes()), //加密时的
盐值
uname // 用户名
);
return authenticationInfo;
}
return null;
}
}

 4. Configure shiro manager and customized Realm in spring.xml

<!--=================shiro相关配置====================-->
<!--配置shiro进行校验时的加密规则-->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--加密规则-->
<property name="hashAlgorithmName" value="MD5" />
<!--是否加盐-->
<property name="hashSalted" value="true" />
<!--是否增加哈希算法进行散列-->
<!-- <property name="hashIterations" value="1024" />-->
</bean>
<!--配置自定义Realm-->
<bean id="myRealm" class="com.chen.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!--配置安全管理器,使用自定义的Realm-->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--配置自定义的Realm-->
<property name="realm" ref="myRealm" />
</bean>
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置拦截后我们的登录请求地址 -->
<property name="loginUrl" value="/loginUI"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 权限配置
anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
me;
perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
user:登录用户才可以访问,包含remember me; logout:退出
-->
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>
</bean>
Rights Profile
anon : anyone can access;
authc : access must be done after logging in, excluding remember me ;
perms : Specify filtering rules, and you can expand permission configuration by yourself;
roles : configure roles;
user : Only logged-in users can access, including remember me ;
logout : exit

5.Configure shiro filter in web.xml

<!-- shiro配置 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filterclass>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

 6. Perform shiro authentication in the controller

package com.chen.controller;

import com.chen.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

@Controller
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping("/login")
    public String login(String uname, String pwd, HttpSession session) {
        System.out.println(uname+"------------------");
        //1 获取 Subject 对象
        Subject subject = SecurityUtils.getSubject();
//2 封装请求数据到 token 对象中
        AuthenticationToken token = new UsernamePasswordToken(uname, pwd);
//3 调用 login 方法进行登录认证
        try {
            //5.验证主体是否能够登录
            subject.login(token);
            session.setAttribute("user", token.getPrincipal().toString());
            return "main";
        } catch (UnknownAccountException e) {
            System.out.println("用户名不存在!");
            return "login";
        } catch (IncorrectCredentialsException e) {
            System.out.println("密码错误!");
            return "login";
        } catch (AuthenticationException e) {
            System.out.println("认证失败,不知道出了什么问题");
            return "login";
        }
    }
}

Chapter 3  Shiro ’s rememberMe function

Shiro provides the RememberMe function . For example, when you visit some websites and close the browser, you can still remember who you are when you open it again next time. You can access it without logging in again the next time you visit.
For example: when not logged in, accessing the /main homepage will be intercepted and redirected to the login page. After logging in, you can access normally
Ask about the homepage of /main ; if the remember me function is used, a cookie will be written to the browser. If you close the browser, you can directly access /main without logging in .
Basic process
1. First select RememberMe on the login page and log in successfully; if you log in through a browser, you will usually
RememberMe 's Cookie is written to the client and saved;
2. Close the browser and reopen it; you will find that the browser still remembers you;
3. When accessing a general web server, you still know who you are and can access it normally;
4. However, if we access the e-commerce platform, if we want to view my order or make payment, we still need to authenticate again.
authenticated to ensure that the current user is still you.
1. Configure cookie settings and rememberMe manager in spring.xml

1. Configure cookie settings for the Remember Me function ;

2. Configure the manager of the remember me function;
3. Reference the manager of the remember me function in the security manager;
4. Configure rememberMe ’s filtering configuration in shiroFilter in the filter ( /**=user )
<!--=================shiro相关配置====================-->
<!--配置shiro进行校验时的加密规则-->
<bean id="credentialsMatcher"
class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!--加密规则-->
<property name="hashAlgorithmName" value="MD5" />
<!--是否加盐-->
<property name="hashSalted" value="true" />
<!--是否增加哈希算法进行散列-->
<!-- <property name="hashIterations" value="1024" />-->
</bean>
<!--配置自定义Realm-->
<bean id="myRealm" class="com.chen.shiro.MyRealm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!--=================记住我功能相关配置====================-->
<!--记住我功能的cookie设置-->
<bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!--设置cookie的属性名-->
<property name="name" value="rememberMe" />
<!--设置cookie存在根目录,可在同一应用服务器内共享-->
<property name="path" value="/" />
<!--通过JavaScript脚本将无法读取到Cookie信息,这样能有效的防止XSS攻击,让网站应用更
加安全-->
<property name="httpOnly" value="true" />
<!--设置cookie的失效时间为30天-->
<property name="maxAge" value="2592000" />
</bean>
<!--记住我功能的管理器配置-->
<bean id="rememberMeManager"
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
<!--引用cookie设置-->
<property name="cookie" ref="simpleCookie" />
<!--默认AES算法,设置cookie的加密算法,采用的是base64的加密-->
<property name="cipherKey" value="#
{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
</bean>
<!--配置安全管理器,使用自定义的Realm-->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!--配置自定义的Realm-->
<property name="realm" ref="myRealm" />
<!--====引用rememberMe功能管理器====================-->
<property name="rememberMeManager" ref="rememberMeManager" />
</bean>
<!-- 配置shiro的过滤器工厂类,id- shiroFilter要和我们在web.xml中配置的过滤器一致 -->
<bean id="shiroFilter"
class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- 调用我们配置的权限管理器 -->
<property name="securityManager" ref="securityManager"/>
<!-- 配置拦截后我们的登录请求地址 -->
<property name="loginUrl" value="/loginUI"/>
<!-- 如果您请求的资源不再您的权限范围,则跳转到错误页面 -->
<property name="unauthorizedUrl" value="/error"/>
<!-- 权限配置 -->
<!-- 权限配置
anon:任何人都可以访问; authc:必须是登录之后才能进行访问,不包括remember
me;
perms:指定过滤规则,可以自己拓展权限配置; roles:配置角色;
user:登录用户才可以访问,包含remember me; logout:退出
-->
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>
</bean>
2. Add a remember me checked checkbox button on the page and set the name attribute to rememberMe
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
</head>
<body>
<div id="content">
    <form class="form-horizontal" action="/login" method="post">
        <div class="form-group">
            <label for="uname" class="col-sm-2 control-label">帐号</label>
            <div class="col-sm-10">
                <input type="text" name="uname" class="form-control" id="uname"
                       placeholder="帐号">
            </div>
        </div>
        <div class="form-group">
            <label for="pwd" class="col-sm-2 control-label">密码</label>
            <div class="col-sm-10">
                <input type="password" name="pwd" class="form-control" id="pwd"
                       placeholder="密码">
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <div class="checkbox">
                    <label>
                        <input type="checkbox" name="rerememberMe"> 记住我
                    </label>
                </div>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <button type="submit" id="login" class="btn btn-primary">登录
                </button>
                <a href="/indexUI">去注册</a>
            </div>
        </div>
    </form>
</div>
</body>
</html>
3. Modify the controller , or check whether the remember me function is checked, and add a remember me mark during authentication.
1. Configure the boolean type request parameter rememberMe and set the default value to false ;
2. When encapsulating the token , add the rememberMe tag;

package com.chen.controller;

import com.chen.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpSession;

@Controller
public class UserController {
    @Autowired
    UserService userService;

    @RequestMapping("/login")
    public String login(String uname, String pwd, @RequestParam(defaultValue = "false") boolean rerememberMe, HttpSession session) {
        System.out.println(uname+"------------------");
        //1 获取 Subject 对象
        Subject subject = SecurityUtils.getSubject();
//2 封装请求数据到 token 对象中
        AuthenticationToken token = new UsernamePasswordToken(uname, pwd,rerememberMe);
//3 调用 login 方法进行登录认证
        try {
            //5.验证主体是否能够登录
            subject.login(token);
            session.setAttribute("user", token.getPrincipal().toString());
            return "main";
        } catch (UnknownAccountException e) {
            System.out.println("用户名不存在!");
            return "login";
        } catch (IncorrectCredentialsException e) {
            System.out.println("密码错误!");
            return "login";
        } catch (AuthenticationException e) {
            System.out.println("认证失败,不知道出了什么问题");
            return "login";
        }
    }
}
4. Test rememberMe function
1. If you directly access the homepage /main without logging in , shiro will intercept and go to the login page; after logging in, you can access the homepage /main normally ;
2. If you do not check Remember me when logging in, closing the browser and accessing the homepage /main will still intercept the login page;
3. Check Remember Me when logging in, close the browser and access the homepage /main for normal access;

Chapter 4 Shiro ’s Logout

1. Set a logout link on the homepage

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>主页</title>
<body>
<img src="/img/index.jpg">
<a href="/logout">退出登录</a>
</body>
</html>
2. Find the shiro filter in the spring.xml configuration file and configure the logout operation
<property name="filterChainDefinitions">
<value>
/=anon
/index = anon
/loginUI = anon
/login = anon
/logout=logout
/WEB-INF/view/login.html = anon
/**/*.js=anon
/**/*.css=anon
/**=authc
/**=user
</value>
</property>

Chapter 6  shiro role authorization authentication

1. Design two hyperlinks on the homepage to simulate viewing user management and system management
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页</title>
</head>
<body>
<h2>内容页</h2>
<a href="/loginOut">退出登录</a>
<hr>
<ul>
    <li><a href="/user">用户管理</a></li>
    <li><a href="/system">系统管理</a></li>
</ul>
</body>
</html>
2. Use the @RequiresRoles("roles") annotation in the controller to enable role verification for requests
   @RequiresRoles("user")
    @RequestMapping("/user")
    public String user(){
        System.out.println("用户管理");
        return "userList";
    }
    @RequiresRoles("admin")
    @RequestMapping("/system")
    public String system(){
        System.out.println("系统管理");
        return "system";
    }
3. Enable shiro annotation support in springmvc.xml
Since shiro annotations are configured in the controller , shiro annotation support needs to be configured in springmvc.xml ;
1. Configure the shiro bean life cycle processor
2. Configure automatic creation of agents;
3. Enable support for shiro annotations

    <!--配置shiro bean生命周期处理器-->
    <bean id="lifecycleBeanPostProcessor"
          class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    <!--配置自动创建代理-->
    <bean
            class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
        <property name="proxyTargetClass" value="true" />
    </bean>
    <!-- 开启shiro注解的支持 -->
    <bean
            class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager" />
    </bean>
4. An exception occurs when accessing two hyperlinks on the homepage, prompting that the operation does not have a corresponding role
The error message is as follows:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have role [admin]
5. Simulate role authentication. In the authorization method of the custom Realm class, manually add a role to the user (later use the database to query whether there is a role), and then check whether the user can access normally.
@Component
public class MyRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
principalCollection) {
System.out.println("授权方法被执行==============");
//创建角色和权限对象
SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
//模拟添加角色
authorizationInfo.addRole("user");
//返回权限
return authorizationInfo;
}
...

Chapter 7 shiro authority authorization authentication

1. Design user addition, deletion, modification and query operations in user management and simulate permission verification respectively.
<body>
<ul>
<li><a href="/user/add">添加用户</a></li>
<li><a href="/user/delete">删除用户</a></li>
<li><a href="/user/find">查看用户</a></li>
<li><a href="/user/revise">修改用户</a></li>
</ul>
</body>
2.shiro configuration reference is as above
3. Use the @RequiresPermissions("permission") annotation in the controller to enable role verification for requests

    @RequiresPermissions("user:add")
    @RequestMapping("/user/add")
    @ResponseBody
    public String add(){
        System.out.println("用户添加操作");
        return "action user add...";
    }
    @RequiresPermissions("user:add")
    @RequestMapping("/user/delete")
    @ResponseBody
    public String delete(){
        System.out.println("用户删除操作");
        return "action user delete...";
    }
    @RequiresPermissions("user:find")
    @RequestMapping("/user/find")
    @ResponseBody
    public String find(){
        System.out.println("用户查看操作");
        return "action user find...";
    }
    @RequiresPermissions("user:revise")
    @RequestMapping("/user/revise")
    @ResponseBody
    public String revise(){
        System.out.println("用户修改操作");
        return "action user revise...";
    }
4. In the authorization method of the custom Realm class, manually add permissions to the user (later use the database to check whether there are permissions), and then check whether access .
package com.chen.shior;

import com.chen.bean.User;
import com.chen.service.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 org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 自定义Realm,通过mybatis查询教据库密码和盐值,让shiro进行身份验证
 */
@Component
public class MyShiroRealm extends AuthorizingRealm {
    @Autowired
    UserService userService;

    //shiro 进行授权操作
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("授权方法被执行==============");
        //1.创建角色和权限对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        //2.1 获取用户登录
        String uname = principalCollection.getPrimaryPrincipal().toString();
        System.out.println("当前登录用户为:"+uname);
        if (uname.equals("admin")){
            //正常查询用户的角色(数据库使用set) 现在模拟赋予角色
            String role ="admin";
            authorizationInfo.addRole(role);
            authorizationInfo.addRole("user");

            //授予权限正常查询用户的权限,现在模拟赋予权限
            authorizationInfo.addStringPermission("user:add");
            authorizationInfo.addStringPermission("user:delete");
            authorizationInfo.addStringPermission("user:find");
            authorizationInfo.addStringPermission("user:revise");
            }else {
            authorizationInfo.addRole("user");
            authorizationInfo.addStringPermission("user:add");
            authorizationInfo.addStringPermission("user:find");
        }
        //返回权限
        return authorizationInfo;
    }

}
.......
5. Test to see if you can access the user management page
The add permission is configured , and you can access it normally by clicking Add User;
Clicking the user to delete will throw an exception as follows:
org.springframework.web.util.NestedServletException: Request processing
failed; nested exception is org.apache.shiro.authz.UnauthorizedException:
Subject does not have permission [user:delete]

Guess you like

Origin blog.csdn.net/weixin_67224308/article/details/131522608