1.依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.7.0</version>
</dependency>
<!-- api注解依赖-->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.9.1.RELEASE</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.7.8</version>
</dependency>
2.配置相关的application配置文件
#端口号
server.port=8090
#数据源
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/shirossm?serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
#sql日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
3. 创建shiro配置类
package com.wt.config;
import com.wt.filter.LoginFilter;
import com.wt.realm.MyRealmt;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy;
import javax.servlet.Filter;
import java.util.HashMap;
/**
* @Author wt
* @Date 2022/8/5 15:39
* @PackageName:com.wt.config
* @ClassName: ShiroConfig
* @Description: TODO
* @Version 1.0
*/
@Configuration
public class ShiroConfig {
@Bean
public DefaultWebSecurityManager securityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(realm());
return securityManager;
}
@Bean
public Realm realm(){
MyRealmt myRealm=new MyRealmt();
myRealm.setCredentialsMatcher(credentialsMatcher());
return myRealm;
}
@Bean
public CredentialsMatcher credentialsMatcher(){
HashedCredentialsMatcher credentialsMatcher=new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("MD5");
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
@Bean(value = "shiroFilter")
public ShiroFilterFactoryBean filterFactoryBean(){
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
factoryBean.setSecurityManager(securityManager());
//设置拦截规则
HashMap<String,String> map=new HashMap<>();
map.put("/login","anon");
map.put("/*.html","anon");
//放行API注解的页面
map.put("/swagger/**","anon");
map.put("/v2/api-docs","anon");
map.put("/swagger-ui.html","anon");
map.put("/swagger-resources/**","anon");
map.put("/webjars/**","anon");
map.put("/favicon.ico","anon");
map.put("/captcha.jpg","anon");
map.put("/csrf","anon");
map.put("/**","authc");
factoryBean.setFilterChainDefinitionMap(map);
//设置自定义认证过滤器
HashMap<String, Filter> filterMap=new HashMap<String, Filter>();
filterMap.put("authc",new LoginFilter());
factoryBean.setFilters(filterMap);
return factoryBean;
}
@Bean //注册filter
public FilterRegistrationBean<Filter> filterRegistrationBean(){
FilterRegistrationBean<Filter> filterRegistrationBean=new FilterRegistrationBean<>();
filterRegistrationBean.setName("shiroFilter");
filterRegistrationBean.setFilter(new DelegatingFilterProxy());
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
}
//开始shiro注解
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
}
4. 创建controller service dao entity filter MyRealm 及全局异常类
(1)创建MyRealm自定义Realm组件
package com.wt.realm;
import com.wt.entity.User;
import com.wt.service.UserServicet;
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 java.util.List;
/**
* @Author wt
* @Date 2022/8/4 15:29
* @PackageName:com.wt.demo03
* @ClassName: MyRealm
* @Description: TODO
* @Version 1.0
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
//进行权限校验时会执行该方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
User primaryPrincipal = (User) principalCollection.getPrimaryPrincipal();
//根据账号查询该用户具有哪些权限
List<String> list = userServicet.finByPermissionByUsername(primaryPrincipal.getUserid());
System.out.println("=============="+list);
if (list!=null&&list.size()>0){
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermissions(list);
return info;
}
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.根据token获取账号
String username = (String) authenticationToken.getPrincipal();
//2.根据账号查询用户信息
User user = userService.findByLogin(username);
if (user!=null){
//从数据库中获取的密码
ByteSource byteSource = ByteSource.Util.bytes(user.getSalt()); //获取盐
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getUserpwd(),byteSource,this.getName());
return info;
}
return null;
}
}
(2) 创建Filter过滤器
package com.wt.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wt.util.CommonResult;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.PrintWriter;
public class LoginFilter extends FormAuthenticationFilter {
//当没有登录时会经过该方法、如果想让他返回json数据必须重写该方法
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
CommonResult result = new CommonResult(5001,"请先登录",null);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(result);
writer.print(json); //响应给客户json数据
writer.flush();
writer.close();
return false;
}
}
(3)创建全局异常类
package com.wt.handler;
import com.wt.util.CommonResult;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Author wt
* @Date 2022/8/5 10:09
* @PackageName:com.wt.erro
* @ClassName: MyException
* @Description: 全局异常类
* @Version 1.0
*/
@ControllerAdvice
public class MyException {
@ExceptionHandler(value = UnauthorizedException.class)
@ResponseBody
public CommonResult auth(UnauthorizedException e){
e.printStackTrace();
return new CommonResult(5002,"权限不足",null);
}
}
(4)配置API注解
package com.wt.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.service.VendorExtension;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.ArrayList;
/**
* @Author wt
* @Date 2022/7/22 19:52
* @PackageName:com.wt.springboot03.config
* @ClassName: MySwagger
* @Description: TODO
* @Version 1.0
*/
@Configuration
public class MySwagger {
@Bean //swagger中所有的功能都封装再Docket类中
public Docket docket(){
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.wt.controller")) //为指定包下的路径生成接口
.build();
return docket;
}
//定义自己的接口文档信息
private ApiInfo apiInfo(){
Contact DEFAULT_CONTACT = new Contact("子不语呀","http://zby.com","66666@qq.com");
ApiInfo apiInfo = new ApiInfo("子非鱼呀", "https:www.zfy.com", "b.2.0", "urn:tos",
DEFAULT_CONTACT, "子非鱼的小屋", "http:www.baidu.com", new ArrayList<VendorExtension>());
return apiInfo;
}
}
(5)使用mybaits-plus自动生成相应的 controller service dao entity
导入mp依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.2</version> </dependency>
package com.wt;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.Collections;
public class Generator {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://localhost:3306/acl_permission?serverTimezone=Asia/Shanghai", "root", "root")
.globalConfig(builder -> {
builder.author("wt") // 设置作者
.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir(".\\src\\main\\java\\"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com") // 设置父包名
.moduleName("wt") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.xml, "src\\main\\resources\\mapper\\")); // 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("acl_user","acl_role","acl_permission")// 设置需要生成的表名
.addTablePrefix("acl_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
.execute();
}
}