Spring Boot 整合 Shiro
Shiro简介
Apache Shiro 是一个开源的轻量级的 Java 安全框架,它提供身份验证,授权,密码管理以及会话管理等功能,相对于 Spring Security ,Shiro 框架更加直观,易用,同时也能提供健壮的安全性。
1.创建项目,添加如下依赖:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
2.Shiro 基本配置,在application.properties中进行配置如下代码
#开启Shrio配置
shiro.enabled=true
#开启Shiro Web配置
shiro.web.enabled=true
#默认的登陆地址
shiro.loginUrl=/login
#登陆成功后的地址
shiro.successUrl=/index
#未授权默认跳转地址
shiro.unauthorizedUrl=/unauthorized
#是否允许通过URL参数实现会话跟踪,如果网站支持Cookie,可以关闭此选项
shiro.sessionManager.sessionIdUrlRewritingEnabled=true
#是否允许通过Cookie实现会话跟踪
shiro.sessionManager.sessionIdCookieEnabled=true
3.配置 Shiro
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.realm.text.TextConfigurationRealm;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ShiroConfig {
@Bean
public Realm realm() {
TextConfigurationRealm realm = new TextConfigurationRealm();
realm.setUserDefinitions("sang=123,user\n admin=123,admin"); //这里配置了两个用户
realm.setRoleDefinitions("admin=read,write\n user=read"); //admin具有读写权限,user具有读权限
return realm;
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/login","anon"); //匿名访问
chainDefinition.addPathDefinition("/doLogin","anon"); //匿名访问
chainDefinition.addPathDefinition("/logout","logout"); //注销登陆
chainDefinition.addPathDefinition("/**","authc"); //其他请求需要认证
return chainDefinition;
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect(); //支持在 Themyleaf 中使用 Shiro 标签
}
}
4.配置登陆接口以及页面访问接口
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@PostMapping("/doLogin")
public String doLogin(String username, String password, Model model) {
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch (AuthenticationException e) {
model.addAttribute("error","用户名密码输入错误!");
return "login";
}
return "redirect:/index";
}
@RequiresRoles("admin")
@GetMapping("/admin")
public String admin() {
return "admin";
}
@RequiresRoles(value = {"admin","user"},logical = Logical.OR)
@GetMapping("/user")
public String user() {
return "user";
}
}
在doLogin方法中,首先创建一个 UsernamePasswordToken实例,然后获取一个Subject对象并调用该对象中的login方法执行登陆操作,在登陆操作执行过程中,当有异常出现时,说明登陆失败,并将错误信息返回给前端页面
对于其他不需要角色就能访问的接口,直接在WebMvc中配置就行,代码如下:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/unauthorized").setViewName("unauthorized");
}
}
5.创建全局异常处理器进行全局异常处理
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class ExceptionController {
@ExceptionHandler(AuthorizationException.class)
public ModelAndView error(AuthorizationException e) {
ModelAndView mv = new ModelAndView("unauthorized");
mv.addObject("error",e.getMessage());
return mv;
}
}
当用户访问未授权的资源时,自动跳转到 unauthorized 这个视图中,并把错误信息显示出来
配置完成后,最后在 resources/template 目录下创建HTML页面进行测试
(1)index.html 首页
<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>Hello, <shiro:principal/></h3>
<h3><a href="/logout">注销登录</a></h3>
<h3><a shiro:hasRole="admin" href="/admin">管理员页面</a></h3>
<h3><a shiro:hasAnyRoles="admin,user" href="/user">普通用户页面</a></h3>
</body>
</html>
(2) login.html 登陆页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<form action="/doLogin" method="post">
<input type="text" name="username"> <br>
<input type="password" name="password"> <br>
<div th:text="${error}"></div>
<input type="submit" value="登陆">
</form>
</div>
</body>
</html>
(3) user.html 普通用户页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>普通用户页面</title>
</head>
<body>
<h1>普通用户页面</h1>
</body>
</html>
(4) admin.html 管理员页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>管理员页面</title>
</head>
<body>
<h1>管理员页面</h1>
</body>
</html>
(5) unauthorized.html 未授权页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>未获授权,非法访问</h3>
<h3 th:text="${error}"></h3>
</body>
</html>
6.进行测试
启动项目,访问登陆页面,分别使用 sang/123 和 admin/123 进行访问,结果如下图所示
sang 用户登陆后所展示的内容
————————————————————————————
admin 用户登陆后所展示的内容
————————————————————————————
登陆成功后,无论 sang 还是 admin 用户,单击 注销登录 都会注销成功,然后回到登陆页面, sang 用户因为不具备管理员权限,因此没有管理员页面的超链接,无法进入管理员页面,如果sang用户手动在地址栏中输入管理员的地址 http:localhost:8080/admin ,则会跳转到未授权页面,如下所示:
注意,必须先用 sang 用户登陆成功后在访问管理员网址才会产生这种结果
这些就是 shiro 的简单使用!