Shiro是一款十分好用的权限管理框架 可以和SpringBoot整合实现页面的权限控制
首先导入pom依赖
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
然后自定义我们的Realm对象 (配置类中需要这个类) 并且需要在Realm类中实现我们的授权和认证(Shiro的核心)
package com.jee.shiro;
import com.jee.entity.User;
import com.jee.mapper.UserMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
//自定义的 UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserMapper userMapper;
//授权(在访问需要权限的页面是 才会进行授权)
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权 AuthorizationInfo");
//授权 登录成功的
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获得当前对象
Subject subject = SecurityUtils.getSubject();
//获得认证中添加的当前用户的信息
User currentUser = (User)subject.getPrincipal();
//一般是通过这个User 查询数据库中对应的权限 然后给他授权
//这里模拟一下就行
System.out.println("id:"+currentUser.getId());
info.addStringPermission("id:"+currentUser.getId());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证 AuthenticationInfo");
//用户名 密码 从数据库中取
// String name = "root";
// String passwod = "123456";
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
User user = userMapper.getUserByName(userToken.getUsername());
//如果用户名不存在
if(user == null){
return null; //抛出异常 用户名不存在的异常
}
//如果用户名通过 就要验证密码了 验证密码是 shiro自己做的
//第一个参数principal 表示存放在当前登录用户中的信息 添加后可以使用subject.getPrincipal方法获得
return new SimpleAuthenticationInfo(user,user.getPassword(),"");
}
}
最后再编写我们的Shiro配置类 实现自定义Shiro
很多的死代码 有一部分是需要我们自己配置的 详细看注释
package com.jee.config;
import com.jee.shiro.UserRealm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean (第三步)
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
//大部分死代码
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/*
anon : 无需验证就可以访问
authc: 必须要认证才可以访问
user: 必须拥有记住我功能才可以访问
perms: 拥有对某个资源的权限才可以访问
role: 拥有某个角色权限才可以访问
*/
Map<String,String> filterMap = new LinkedHashMap<>();
//只需要自己填写一些需要验证的请求即可
//将'/delete'的请求设置需要验证才可以访问
filterMap.put("/delete","authc");
//将'/query'的请求设置为: 必须通过授权才可以 并且添加授权的字段为id:3
filterMap.put("/query","perms[id:3]");
bean.setFilterChainDefinitionMap(filterMap);
//需要手动设置 设置登录的页面 (在Control层写一个toLogin的请求 跳转到真正的登录页面
bean.setLoginUrl("/toLogin");
return bean;
}
//DefaultWebSecurityManager (第二步)
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){
//死代码
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建 realm 对象 (第一步) 需要自定义类
@Bean
public UserRealm userRealm(){
//死代码 只需要return 自定义的Realm类即可
return new UserRealm();
}
}
相应的Controller:
package com.jee.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jee.entity.User;
import com.jee.mapper.UserMapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class MyController {
@Autowired
private UserMapper userMapper;
@RequestMapping("/aa")
@ResponseBody
public String fun1() throws JsonProcessingException {
List<User> allUser = userMapper.getAllUser();
ObjectMapper mapper = new ObjectMapper();
return (mapper.writeValueAsString(allUser));
}
@RequestMapping("/bb")
@ResponseBody
public String fun2(){
return "Hello Spring";
}
@GetMapping("/query")
public String fun3(){
return "user/query";
}
@GetMapping("/delete")
public String fun4(){
return "user/delete";
}
@RequestMapping("/toLogin")
public String fun5(){
return "user/login";
}
@PostMapping("/login")
public String fun6(String userName,String passWord){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
//设置记住我
token.setRememberMe(true);
try {
subject.login(token);//执行登录的方法 如果没有异常就说明Ok了
return "hh";
}catch (UnknownAccountException e){//用户名不存在
System.out.println("用户名错误");
return "user/login";
}catch (IncorrectCredentialsException e){//密码不存在
System.out.println("密码错误");
return "user/login";
}
}
}
SpringBoot集成Swagger2
导入依赖
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
编写相应的配置类:
package com.jee.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
@Configuration
//开启Swagger2功能
@EnableSwagger2
public class SwaggerConfig {
//配置Swagger的Docket的bean实例
@Bean
public Docket docket(){
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo())
.select()//选择扫描的方式
//RequestHandlerSelectors 配置扫描的方式
//basePackage: 指定要扫描的包(常用)
//any : 扫描全部
//none: 全都不扫描
//withClassAnnotation : 扫描类上面的注解,参数是一个注解的反射对象
//withMethodAnnotation : 扫描方法上的注解
.apis(RequestHandlerSelectors.basePackage("com.jee.controller"))
.build();
}
//配置Swagger的信息 apiInfo
private ApiInfo apiInfo(){
//作者信息
Contact contact = new Contact("Jee","(url)xxx","[email protected]");
return new ApiInfo(
"Jee的SwaggerAPI文档",
"(文档的描述)",
"(版本号)",
"(url)",
contact,
"(license)",
"licenseUrl",
new ArrayList()
);
}
}
然后可以去swagger-ui界面查看相关信息