引言
Shiro是一个开源的安全框架,用于在Java应用中实现身份验证、授权、会话管理和加密。它提供了一种简单而强大的方式来处理用户认证和授权,使开发者能够轻松地实现权限管理。本文将带您从入门到实战,一步步掌握Shiro框架。
一、Shiro入门
1.1 Shiro的核心组件
Shiro的核心组件包括:
- Subject:主体,即当前用户。
- SecurityManager:安全管理器,Shiro的核心,负责管理内部组件。
- Realm:域,用于进行用户认证和授权。
- SessionManager:会话管理器,用于管理Subject的会话。
- Cryptography:加密,提供加密和解密服务。
1.2 Shiro的工作流程
- Subject提交认证请求。
- SecurityManager委托Authenticator进行认证。
- Authenticator委托Realm进行认证。
- Realm从数据源获取用户信息,进行认证。
- Subject提交授权请求。
- SecurityManager委托Authorizer进行授权。
- Authorizer委托Realm进行授权。
- Realm从数据源获取用户权限,进行授权。
二、Shiro配置
2.1 创建Shiro工程
- 创建一个Maven工程。
- 添加Shiro依赖。
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
2.2 配置Shiro
在web.xml中配置Shiro过滤器。
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
<init-param>
<param-name>configLocation</param-name>
<param-value>/WEB-INF/classes/shiro.ini</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在src/main/resources目录下创建shiro.ini文件,配置Shiro。
[main]
# 设置Shiro的SecurityManager
securityManager.realms=authRealm
# 设置默认的登录成功页面
loginUrl=/login.jsp
successUrl=/index.jsp
# 设置未经授权访问资源的默认处理方式
unauthorizedUrl=/unauthorized.jsp
2.3 配置Realm
在src/main/java目录下创建AuthRealm.java文件,实现Realm接口。
package com.example.shiro;
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.Realm;
public class AuthRealm implements Realm {
@Override
public String getName() {
return "authRealm";
}
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 从token中获取用户名和密码
String username = (String) token.getPrincipal();
String password = new String((char[]) token.getCredentials());
// 根据用户名从数据源获取用户信息
// ...
// 返回AuthenticationInfo对象
return new SimpleAuthenticationInfo(username, password, getName());
}
@Override
public AuthorizationInfo getAuthorizationInfo(AuthenticationToken token) {
// 从token中获取用户名
String username = (String) token.getPrincipal();
// 根据用户名从数据源获取用户权限
// ...
// 返回AuthorizationInfo对象
return new SimpleAuthorizationInfo();
}
}
三、Shiro实战
3.1 用户认证
在shiro.ini文件中配置登录成功页面和登录失败页面。
[main]
# ...
loginUrl=/login.jsp
successUrl=/index.jsp
unauthorizedUrl=/unauthorized.jsp
在login.jsp文件中,使用Shiro的formAuthenticationFilter过滤器进行表单认证。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Login</title>
</head>
<body>
<form action="login" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username" />
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password" />
</div>
<div>
<input type="submit" value="Login" />
</div>
</form>
</body>
</html>
在LoginController.java文件中,处理登录请求。
package com.example.shiro.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class LoginController {
@RequestMapping("/login")
public String login(String username, String password) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
return "redirect:index.jsp";
} catch (Exception e) {
return "redirect:login.jsp";
}
}
}
3.2 用户授权
在shiro.ini文件中配置权限。
[main]
# ...
loginUrl=/login.jsp
successUrl=/index.jsp
unauthorizedUrl=/unauthorized.jsp
authc=authc, roles[user]
在AuthRealm.java文件中,实现用户权限获取方法。
@Override
public AuthorizationInfo getAuthorizationInfo(AuthenticationToken token) {
String username = (String) token.getPrincipal();
// 根据用户名从数据源获取用户权限
Set<String> roles = new HashSet<>();
roles.add("user");
roles.add("admin");
// 返回AuthorizationInfo对象
return new SimpleAuthorizationInfo(roles);
}
在页面中,使用Shiro的hasRole和isPermitted方法进行权限判断。
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags/shiro" %>
<html>
<head>
<title>Index</title>
</head>
<body>
<h1>Welcome, ${principal.username}!</h1>
<shiro:hasRole name="admin">
<div>Admin Only</div>
</shiro:hasRole>
<shiro:isPermitted name="delete">
<div>Permitted to delete</div>
</shiro:isPermitted>
</body>
</html>
四、总结
通过本文的介绍,您应该已经掌握了Shiro框架的基本用法。在实际项目中,您可以根据需求进行扩展和定制。Shiro是一个非常强大且灵活的权限管理框架,相信它能为您的Java应用带来很大的便利。
