一、相关框架简介
1.1 spring boot
spring boot是由Pivotal团队开发的全新框架,其主要目的是使搭建spring web项目变得简单、快速,能快速进入到项目的业务逻辑开发。其主要的配置是在application命名的文件中,主要有application.properties和application.yml两种配置方式,spring boot项目启动时会默认到项目路径下去寻找application的文件并读取内容。
1.2 Shiro
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。shiro主要由三个主要组建组成:Subject(当前操作用户,不仅仅是人或事物的对象,还可能是线程),SecurityManager(shiro的核心框架,用来管理内部组建实例并提供安全管理的服务),Realm(是shiro和安全数据数据的桥梁,当对用户进行授权或身份验证时,shiro会从配置的Realm中查找用户和其相关权限)。Realm相当于我们开发过程中的dao层,它封装了数据连接的细节。
1.3 Swagger
swagger是目前最受欢迎的Rest Apis文档生成工具之一,它可以生成支持互动类型的API控制台,生成可以在不能平台运行的客户端SDK,Swagger 文档提供了一个方法,使我们可以用指定的 JSON 或者 YAML 摘要来描述你的 API,包括了比如 names、order 等 API 信息等优点。
二、基本接口的提供
以user为列,提供相关接口,具体实现忽略。controller代码如下:
package com.why.greenhouse.back.user.controller;
import com.why.greenhouse.back.config.filter.ShiroProperties;
import com.why.greenhouse.back.user.entity.User;
import com.why.greenhouse.back.user.service.UserService;
import com.why.greenhouse.back.user.model.request.UserRequest;
import com.why.greenhouse.back.user.model.response.UserResponse;
import java.util.List;
import java.util.Map;
import com.why.greenhouse.back.utils.UserUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 描述:user控制层
*
* @author why
* @date 2018-07-07 14:17:51
*/
@RestController
@RequestMapping(path = "user")
public class UserController {
@Autowired
private UserService userService;
/**
* 描述:根据Id 查询
*
* @param id userid
*/
@GetMapping("findById")
public UserResponse findById(@RequestParam("id") Long id) throws Exception {
UserResponse userResponse = userService.queryUserById(id);
return userResponse;
}
/**
* 描述:创建user
*
* @param userRequest
*/
@PostMapping("add")
public void add(@RequestBody UserRequest userRequest) throws Exception {
userService.addUser(userRequest);
}
/**
* 描述:删除user
*
* @param id userid
*/
@DeleteMapping("deleteById")
public void deleteById(@RequestParam("id") Long id) throws Exception {
userService.deleteUser(id);
}
/**
* 描述:更新user
*
* @param userRequest userRequest
*/
@PostMapping("update")
public void update(@RequestBody UserRequest userRequest) throws Exception {
userService.updateUser(userRequest);
}
@Autowired
private ShiroProperties shiroProperties;
/**
* 描述:查询所有user
*/
@PostMapping("queryAll")
public List queryAll() throws Exception {
for(String s : shiroProperties.getFilterRules()){
System.out.println(s);
}
return userService.queryAll();
}
/**
* 描述:查询所有user
*/
@GetMapping("login")
public void login(){
// public void login(@RequestParam(name = "name") String name){
// User user = userService.queryByName(name);
// if (user==null){
// throw new RuntimeException("不存在改用户");
// }
System.out.println("的点点滴滴多多多");
}
}
三、shiro Filter相关代码
添加相关依赖,依赖中有一些自己测试用的包,该功能没有用到
4.0.0
com.why
greenhouse
pom
1.0-SNAPSHOT
common
front
back
core
Green House Server
Green House Server
org.springframework.boot
spring-boot-starter-parent
1.5.3.RELEASE
UTF-8
UTF-8
1.8
2.7.0
org.springframework.boot
spring-boot-starter-data-jpa
org.springframework.boot
spring-boot-starter-cache
org.projectlombok
lombok
1.16.18
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-aop
org.springframework.boot
spring-boot-starter-test
test
mysql
mysql-connector-java
5.1.21
io.springfox
springfox-swagger2
${swagger.version}
reflections
org.reflections
io.springfox
springfox-swagger-ui
${swagger.version}
com.alibaba
fastjson
1.2.16
org.apache.shiro
shiro-all
1.2.5
com.alibaba
druid
RELEASE
org.apache.shiro
shiro-spring
1.4.0
通过@Bean方式注入自己定义的拦截和shiro相关的类
package com.why.greenhouse.back.config.filter;
import org.apache.shiro.mgt.SecurityManager;
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.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author why
* 拦截器实例化
*/
@Configuration
@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
public class LoginFilterBean{
@Autowired
private ShiroProperties shiroProperties;
@Bean
public LoginFilter loginFilter(){
return new LoginFilter();
}
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
return securityManager;
}
@ConditionalOnMissingBean
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){
//打印日志便于查看是否进入该拦截器
System.out.println("LoginFilterBean.shirFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
Map filterMap = new HashMap<>(20);
//定义拦截器名称
filterMap.put("hasToken",new LoginFilter());
shiroFilterFactoryBean.setFilters(filterMap);
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map filterChainMap = new HashMap<>(20);
//从配置文件中自定义拦截规则的相关配置信息
List filters = shiroProperties.getFilterRules();
if (null!=filters){
for (String str: filters) {
String[] temp = str.split("==>");
if (temp.length != 2) {
throw new IllegalStateException("过滤规则配置不正确,格式:url==>filters");
}
filterChainMap.put(temp[0],temp[1]);
}
}
//把自己定义的拦截相关规则交给shiro管理
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
shiroFilterFactoryBean.setLoginUrl("/user/login");
shiroFilterFactoryBean.setSuccessUrl("/");
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
return shiroFilterFactoryBean;
}
/**
* 加入注解的使用,不加入这个注解不生效
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
application.yml文件相关配置信息如下:
server:
tomcat:
uri-encoding: UTF-8
max-threads: 3000
port: 15030
compression:
enabled: true
spring:
datasource:
password: 1pTVg0ld@1909
tomcat:
max-idle: 10
min-idle: 5
test-on-borrow: false
test-while-idle: true
time-between-eviction-runs-millis: 18800
validation-query: SELECT 1
initial-size: 5
max-wait: 3000
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/why?useUnicode=true&characterEncoding=utf8&autoReconnect=true&failOver
username: root
hikari:
read-only:
messages:
cache-seconds: -1
always-use-message-format: false
fallback-to-system-locale: true
basename: i18n/messages
encoding: UTF-8
jpa:
show-sql: true
database: MYSQL
generate-ddl: false
hibernate:
ddl-auto: update
properties:
globally_quoted_identifiers: true
use_query_cache: false
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
shiro:
filter-rules:
- /swagger-ui.html==>anon
- /swagger-resources/**==>anon
- //webjars/**==>anon
- /v2/**==>anon
- /user/login/**==>anon
- /user/queryAll/**==>anon
- /**==>authc
这个时候还访问不了swagger页面,需要对swagger进行相关的配置,配置类如下:
package com.why.greenhouse.back.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* swagger配置
* @author why
*/
@Configuration
@EnableSwagger2
public class SwaggerConfiguration {
@Bean
public Docket createRestApi(){
//add head start
ParameterBuilder tokenPar = new ParameterBuilder();
List pars = new ArrayList<>();
tokenPar.name("token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
//add head end
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.why.greenhouse"))
.paths(PathSelectors.any())
.build()
.globalOperationParameters(pars);
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("GREEN TOKEN SERVER API information")
.description("GREEN TOKEN SERVER API information")
.version("1.0")
.build();
}
}
四、代码演示及相关问题修改
这个时候我们访问http://localhost:15030/swagger-ui.html时出现如下情况:
我们的接口没有了,再看看请求
和后台日志
显然是我们请求swagger页面的时候有的页面被拦截器拦截住了,通过请求地址可以看出是在/swagger-resources/configuration请求后跳转到我们拦截之后的接口的,因此对application.yml文件的配置做了如下修改
其中:
- /swagger-resources/**==>anon
改成
- /swagger-resources/**/**==>anon
修改之后重新启动项目
我们的接口出来了,
-
/user/queryAll/**==>anon调用不需要验证的接口:
可以查到内容,再查看需要登录的接口:
后台打印
的点点滴滴多多多
说明进入了我们的拦截指定的接口
五、结束
本项目完全为测试所用,接口没有实际意义,本文只是对shiro Filter做最基本的简单的登录功能验证。踩完后面的坑再写个稍微深入一点的。