springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等!
1.引入Shiro依赖并使用Thymeleaf模版技术进行验证:
<!-- springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(1) -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-web-starter</artifactId>
<version>1.4.0</version>
</dependency>
<!-- springboot整合Thymeleaf视图层模版引擎 -->
<!-- springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(2) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(3)为了能在Thymeleaf中使用shiro标签,引入依赖 -->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
2.在application.properties配置Shiro基本信息
# springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(4)
# 开启Shiro配置,默认为true
shiro.enabled=true
# 开启Shiro Web配置,默认为true
shiro.web.enabled=true
# 登录地址,默认为login.jsp
shiro.loginUrl=/login
# 登录成功地址,默认为/
shiro.successUrl=/index
# 未授权默认跳转地址
shiro.unauthorizedUrl=/unauthorized
# 是否允许通过URL参数实现会话跟踪,如果网站支持Cookie,可以关闭此选项,默认为true
shiro.sessionManager.sessionIdUrlRewretingEnabled=true
# 是否允许通过Cookie实现会话跟踪,默认为true
shiro.sessionManager.sessionIdCookieEnabled=true
3.创建ShiroConfig.java,提供用户信息和权限设置
package com.steno.propertiestest.common;
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;
/**
* springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(5)
*/
@Configuration
public class ShiroConfig {
/**
* 配置两个用户,sang/123,admin/123,对应角色user和admin,
* 其中user聚优read权限,admin具有read\wirte权限
* @return
*/
@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");
return realm;
}
/**
* 配置基本的过滤规则:
* "/login":可以匿名访问
* "/doLogin":可以匿名访问
* "/logout":注销登录请求
* "/**":其余请求都需要认证后才能访问
* @return
*/
@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;
}
/**
* 为了支持Thymeleaf中使用shiro标签,增加shiroDialect,如果不需要则可以不提供
* @return
*/
@Bean
public ShiroDialect shiroDialect(){
return new ShiroDialect();
}
}
4.配置登录访问接口和页面信息
(1)Controller
package com.steno.propertiestest.controller;
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;
/**
* springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(6)
*/
@Controller
public class UserController {
/**
* 登录验证(使用UsernamePasswordToken和subject)
* @param username
* @param password
* @param model
* @return
*/
@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";
}
/**
* admin角色可访问的方法
* @return
*/
@RequiresRoles("admin")
@GetMapping("/admin")
public String admin(){
return "admin";
}
/**
* admin或者user角色可访问的方法
* @return
*/
@RequiresRoles(value = {"admin", "user"}, logical = Logical.OR)
@GetMapping("/user")
public String user(){
return "user";
}
}
(2)配置不需要角色即可访问的接口设置:
package com.steno.propertiestest.common;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyWebMVCConfig implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
System.out.println("==========静态资源拦截!============");
//将所有/static/** 访问都映射到classpath:/static/ 目录下
registry.addResourceHandler("/static/**/").addResourceLocations("classpath:/static/");
}
/**
* springboot整合Shiro安全框架,提供身份验证、授权、密码管理、回话管理等(7)
* 设置不需要角色就可访问的接口
* @param registry
*/
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/unauthorized").setViewName("unauthorized");
}
}
(3)创建全局异常处理Controller
package com.steno.propertiestest.common;
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 {
/**
* 用户访问未授权的资源时,跳转到unauthorized视图,并携带错误信息
* @param e
* @return
*/
@ExceptionHandler(AuthorizationException.class)
public ModelAndView error(AuthorizationException e){
ModelAndView modelAndView = new ModelAndView("unauthorized");
modelAndView.addObject("error", e.getMessage());
return modelAndView;
}
}
(4)创建页面信息:
I、创建登录页面login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="/doLogin" method="post">
<input type="text" name="username" placeholder="用户名"><br>
<input type="password" name="password" placeholder="密码"><br>
<div th:text="${error}"></div>
<input type="submit" value="登录">
</form>
</body>
</html>
II、登录成功后展示页面index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>登录成功后的页面</title>
</head>
<body>
<h3>hello, <shiro:principal/></h3>
<a href="/logout">注销登录</a>
<a shiro:hasRole="admin" href="/admin">管理员页面</a>
<a shiro:hasAnyRoles="admin,user" href="/user">普通用户页面</a>
</body>
</html>
III、admin角色成功登录页面展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>管理员信息展示页面</title>
</head>
<body>
<h1>管理员信息展示页面</h1>
</body>
</html>
IIII、user角色成功登录页面展示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>普通的用户信息展示页面</title>
</head>
<body>
<h1>普通的用户信息展示页面</h1>
</body>
</html>
IIIII、无权限访问的页面展示
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Shiro授权失败的展示页面</title>
</head>
<body>
<h3>未获授权,非法访问</h3>
<h3 th:text="${error}"></h3>
</body>
</html>
5.测试访问
(1)登录
http://localhost:8081/login
(2)admin角色登录展示http://localhost:8081/index
进入管理员页面http://localhost:8081/admin
进入普通用户页面http://localhost:8081/user
(3)user角色登录展示http://localhost:8081/index
进入普通用户页面http://localhost:8081/user
无授权访问展示(即user用户访问admin页面)http://localhost:8081/admin