springboot+mybaitsPlus+jwt+SpringSecurity

2019-01-06 21:28:59378人围观
简单来说SpringBoot整合了许多优秀的框架,避免手动创建过多的xml,SpringBoot最大的特点就是约定大于配置MybaitsPlus作为Mybaits升级版,功能强大,扩展了代码生成,提供

简单来说SpringBoot整合了许多优秀的框架,避免手动创建过多的xml,SpringBoot最大的特点就是约定大于配置

MybaitsPlus作为Mybaits升级版,功能强大,扩展了代码生成,提供基本的增删改查功能

Jwt全称JSON Web Token是目前最流行的跨域身份验证解决方案

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。


SpringBoot优点

1:快速构建项目

2:对主流开发框架的无配置集成

3:项目可独立运行,无需外部依赖serverlet容器

4:提高了开发部署效率

MybaitsPlus

   Mybatis-Plus是一个Mybatis的增强工具,它在Mybatis的基础上做了增强,却不做改变。我们在使用Mybatis-Plus之后既可以使用Mybatis-Plus的特有功能,又能够正常使用Mybatis的原生功能。Mybatis-Plus(以下简称MP)是为简化开发、提高开发效率而生,但它也提供了一些很有意思的插件,比如SQL性能监控、乐观锁、执行分析等。

JWT

JWT是json web token缩写。它将用户信息加密到token里,服务器不保存任何用户信息。服务器通过使用保存的密钥验证token的正确性,只要正确即通过验证。 优点是在分布式系统中,很好地解决了单点登录问题,很容易解决了session共享的问题。 缺点是无法作废已颁布的令牌/不易应对数据过期

SpringSecuity

Spring Security是为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了完整的安全性解决方案,可以在Web请求级别和方法调用级别处理身份认证和授权充分利用了Spring IOC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能。
下面介绍集成他们的步骤:
首先引入依赖(这里使用SpringBoot2.2版本)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description></description>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</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>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

在application.yml配置mybaitsPlus以及数据库配置

server:
port: 8080//端口随意
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=gbk&zeroDateTimeBehavior=convertToNull&useSSL=false&allowMultiQueries=true&serverTimezone=UTC
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
mybatis-plus:
mapper-locations: classpath*:/mapper/**Mapper.xml
type-aliases-package:
global-config:
#主键类型 0:"数据库ID自增", 1:"用户输入ID",2:"全局唯一ID (数字类型唯一ID)", 3:"全局唯一ID UUID";
id-type: 2
#字段策略 0:"忽略判断",1:"非 NULL 判断"),2:"非空判断"
field-strategy: 2
#驼峰下划线转换
db-column-underline: true
#刷新mapper 调试神器
refresh-mapper: true
#数据库大写下划线转换
#capital-mode: true
#序列接口实现类配置
#key-generator: com.baomidou.springboot.xxx
#逻辑删除配置(下面3个配置)
logic-delete-value: 0
logic-not-delete-value: 1
#自定义SQL注入器
#sql-injector: com.baomidou.mybatisplus.mapper.LogicSqlInjector
#自定义填充策略接口实现
#meta-object-handler: com.baomidou.springboot.xxx
configuration:
map-underscore-to-camel-case: true
cache-enabled: false

mybaitsPlusConfig配置

package com.example.demo.config;

import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybaitsPlusConfig {
@Bean
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
//sql性能分析,最大执行时间为1000
performanceInterceptor.setMaxTime(1000);
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
@Bean//集成分页
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
}

新建MybaitsPlus生成类

package com.example.demo.genteor;

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.DbType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;


import java.util.ResourceBundle;

/**
* mybait代码生产器
*/
public class MybaitsPlusGenteor {
private ResourceBundle resourceBundle = ResourceBundle.getBundle("Mybiats-plus");

private GlobalConfig globalConfig = new GlobalConfig();

private DataSourceConfig dataSourceConfig = new DataSourceConfig();

private StrategyConfig strategyConfig = new StrategyConfig();

private PackageConfig packageConfig = new PackageConfig();

public void run(){
AutoGenerator autoGenerator = new AutoGenerator();
buildGlobalConfig();
buildDataSourceConfig();
buildStrategyConfig();
buildPackageConfig();
autoGenerator.setGlobalConfig(globalConfig);
autoGenerator.setDataSource(dataSourceConfig);
autoGenerator.setStrategy(strategyConfig);
autoGenerator.setPackageInfo(packageConfig);
autoGenerator.execute();
}

public static void main(String[] args) {
MybaitsPlusGenteor mybaitsPlusGenteor = new MybaitsPlusGenteor();
mybaitsPlusGenteor.run();
}

public void buildGlobalConfig(){
globalConfig.setAuthor(resourceBundle.getString("author"));
globalConfig.setActiveRecord(true);
globalConfig.setEnableCache(false);
globalConfig.setBaseResultMap(true);
globalConfig.setOpen(false);
globalConfig.setBaseColumnList(true);
globalConfig.setFileOverride(true);
globalConfig.setOutputDir(resourceBundle.getString("outPutDir"));
globalConfig.setMapperName("%sMapper");
globalConfig.setXmlName("%sMapper");
globalConfig.setServiceName("%sService");
globalConfig.setServiceImplName("%sServiceImpl");
globalConfig.setControllerName("%sController");
}

public void buildDataSourceConfig(){
dataSourceConfig.setDbType(DbType.MYSQL);
dataSourceConfig.setTypeConvert(new MySqlTypeConvert(){
@Override
public DbColumnType processTypeConvert(String fieldType) {
return super.processTypeConvert(fieldType);
}
});
dataSourceConfig.setDriverName(resourceBundle.getString("driverCalss"));
dataSourceConfig.setUrl(resourceBundle.getString("dburl"));
dataSourceConfig.setUsername(resourceBundle.getString("dbUserName"));
dataSourceConfig.setPassword(resourceBundle.getString("dbPassWord"));
}

public void buildStrategyConfig(){
strategyConfig.setDbColumnUnderline(true);
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
strategyConfig.setTablePrefix(new String[]{resourceBundle.getString("tablePrefix")});
strategyConfig.setInclude(new String[]{resourceBundle.getString("tableName")});
}

public void buildPackageConfig(){
packageConfig.setParent(resourceBundle.getString("package"));
}
}

springSecurity配置:

新建认证过滤器

package com.example.demo.filter;


import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;

/**
* token生成
*/
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {


private AuthenticationManager authenticationManager;

public JwtLoginFilter(AuthenticationManager authenticationManager){
this.authenticationManager=authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String userName = request.getParameter("userName");
String userPassword=request.getParameter("userPassword");
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName,userPassword,new ArrayList<>()));
}

@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token =Jwts.builder().setSubject(((org.springframework.security.core.userdetails.User) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis()+60*60*24*1000))
.signWith(SignatureAlgorithm.HS512,"JwtSerct").compact();
response.setHeader("Authorization","Bearer"+token);
}
}

新建检验token过滤器

package com.example.demo.filter;

import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;

/*
* token校验
*/
public class JwtAuthenzacationFilter extends BasicAuthenticationFilter {

private AuthenticationManager authenticationManager;

public JwtAuthenzacationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
String token = request.getParameter("token");
if (token == null || !token.startsWith("Bearer")){
chain.doFilter(request,response);
return;
}
UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
chain.doFilter(request,response);
}

private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token=request.getParameter("token");
if (token!=null){
String user = Jwts.parser().setSigningKey("JwtSerct")
.parseClaimsJws(token.replace("Bearer",""))
.getBody().getSubject();
if (user!=null){
return new UsernamePasswordAuthenticationToken(user,null,Collections.emptyList());
}
return null;
}
return null;
}

}

扩展userDeatilService

扩展userDeatilService

package com.example.demo.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Collections;

@Service
public class UserDetailServiceImpl implements UserDetailsService {

@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
EntityWrapper<User> entityWrapper = new EntityWrapper<>();
entityWrapper.eq("user_name",s);
User user = userService.selectOne(entityWrapper);
if (user==null){
return null;
}
return new org.springframework.security.core.userdetails.User(user.getUserName(),user.getUserPassword(),Collections.emptyList());
}
}

webSecurityConfig配置

package com.example.demo.config;

import com.example.demo.filter.JwtAuthenzacationFilter;
import com.example.demo.filter.JwtLoginFilter;
import com.example.demo.service.impl.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailServiceImpl userDetailService;//自定义UserDetailSetvice
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST,"/singup")
.permitAll().anyRequest().authenticated().and().addFilter(new JwtLoginFilter(authenticationManager()))
.addFilter(new JwtAuthenzacationFilter(authenticationManager()))
.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(bCryptPasswordEncoder);
}
}

代码已上传到码云,地址:https://gitee.com/TangThomas/demo.git

分享到: