相信很多做技术的朋友都做过前后端分离项目,项目分离后认证就靠JWT,费话不多说,直接上干活(写的不好还请多多见谅,大牛请绕行)

直接上代码,项目为Maven项目,结构如图:

包分类如下:

com.api.config  相关配置类

com.api.ctrl  controller层

com.api.entity  相关实体类

com.api.repo   jpa仓库相关

com.api.serice  service层相关

ApiApplication 为启动类

主要配置核心类如下:

JWTAuthenticationFilter

package com.api.config;

import com.api.entity.User;
import com.api.repo.UserRepo;
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.ArrayList; public class JWTAuthenticationFilter extends BasicAuthenticationFilter { private UserRepo userRepo; public JWTAuthenticationFilter(AuthenticationManager authenticationManager,UserRepo userRepo) {
super(authenticationManager);
this.userRepo = userRepo;
} @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String header = request.getHeader("Authorization");
//如果不包含Bearer则退出
if(header != null && !header.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.getHeader("Authorization");
if (token != null) {
// parse the token.
String user = Jwts.parser()
.setSigningKey("HSMyJwtSecret".getBytes())
.parseClaimsJws(token.replace("Bearer ", ""))
.getBody()
.getSubject();
if (user != null) {
Integer userId = Integer.valueOf(user.split(":")[0]);
User currUser = userRepo.findById(userId).orElse(null);
if(currUser != null){
return new UsernamePasswordAuthenticationToken(currUser, null, new ArrayList<>());
}
return new UsernamePasswordAuthenticationToken(new User(), null, new ArrayList<>());
}
}
return null;
}
}
JWTLoginFilter
package com.api.config;

import com.api.entity.User;
import com.fasterxml.jackson.databind.ObjectMapper;
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; 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 {
try {
User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
user.getUsername(),
user.getPassword(),
new ArrayList<>()
)
); }catch (Exception e){
throw new RuntimeException(e);
}
} @Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
String token = Jwts.builder()
.setSubject(((JwtUser) authResult.getPrincipal()).getUsername())
.setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 1000))
.signWith(SignatureAlgorithm.HS256,"HSMyJwtSecret".getBytes())
.compact();
response.addHeader("Authorization", "Bearer " + token);
response.getOutputStream().println(token);
}
}
MyUserDetailService
package com.api.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component; import java.util.Collection; @Component
public class MyAuthencationProvider implements AuthenticationProvider { @Autowired
private MyUserDetailService myUserDetailService; @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getPrincipal().toString();
JwtUser jwtUser = (JwtUser) myUserDetailService.loadUserByUsername(username);
Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
return new UsernamePasswordAuthenticationToken(jwtUser, jwtUser.getPassword(), authorities);
} @Override
public boolean supports(Class<?> aClass) {
return true;
}
}
MyUserDetailService
package com.api.config;

import com.api.entity.User;
import com.api.repo.UserRepo;
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.Component; @Component
public class MyUserDetailService implements UserDetailsService { @Autowired
private UserRepo userRepo; @Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepo.findFirstByUsername(s);
if(user != null){
JwtUser jwtUser = new JwtUser(String.format("%s:%s",String.valueOf(user.getId()),user.getUsername()),user.getPassword());
return jwtUser;
}
throw new UsernameNotFoundException("用户名未找到");
}
}
WebSecurityConfig
package com.api.config;

import com.api.repo.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(-1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private MyAuthencationProvider myAuthencationProvider;
@Autowired
private UserRepo userRepo; @Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST, "/register").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTLoginFilter(authenticationManager()))
.addFilter(new JWTAuthenticationFilter(authenticationManager(),userRepo));
} @Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthencationProvider);
} }
JwtUser
package com.api.config;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; public class JwtUser implements UserDetails { private String username;
private String password; public JwtUser(String username,String password){
this.username = username;
this.password = password;
} @Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
} @Override
public String getPassword() {
return password;
} @Override
public String getUsername() {
return username;
} @Override
public boolean isAccountNonExpired() {
return false;
} @Override
public boolean isAccountNonLocked() {
return false;
} @Override
public boolean isCredentialsNonExpired() {
return false;
} @Override
public boolean isEnabled() {
return false;
} }
MyMvcConfigurer
package com.api.config;

import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.SecurityConfig;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
@AutoConfigureBefore(SecurityConfig.class)
public class MyMvcConfigurer implements WebMvcConfigurer { @Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}

以上为config包下全部内容

项目POM.xml配置如下

<?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.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.api</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<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.github.wenhao</groupId>
<artifactId>jpa-spec</artifactId>
<version>3.2.3</version>
</dependency> <dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.3.1</version>
</dependency> <dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency> </dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<compilerArgs>
<arg>-verbose</arg>
<arg>-Xlint:all,-options,-path</arg>
</compilerArgs>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin> <plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>com.api.ApiApplication</mainClass>
</manifest>
</archive>
</configuration> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>@</delimiter>
<delimiter>#{*}</delimiter>
<delimiter>#</delimiter>
</delimiters>
</configuration>
</plugin>
</plugins>
</build> <repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories> </project>

以下为其他包结构以及类文件

以上配置成功后即可以POST方式访问

http://localhost:8080/login?username=xxx&password=xx 认证成功后会在返回jwt,下次请求认证的资源在header里边带上Authorization Bearer xxxxxx

即可。

最新文章

  1. ABP(现代ASP.NET样板开发框架)系列之5、ABP启动配置
  2. Apache DdlUtils入门
  3. HuffmanTree的浅析和在C#中的算法实现
  4. Maven 依赖管理
  5. maven入门程序(二)
  6. 【转】Android通过Wifi来调试你的应用
  7. 微信支付 v 3.3.6
  8. .NET Core R2
  9. Flask-WTF 入门使用P1
  10. glReadPixel 读取数据错误问题
  11. netty 的 JBoss Marshalling 编码解码
  12. Java并发编程笔记之ArrayBlockingQueue源码分析
  13. maven -maven.test.skip skipTests
  14. 关于windows下的虚拟机Homestead在推送代码上github 步骤
  15. MySql 应用语句
  16. Ubuntu下Tomcat绑定80端口(zz)
  17. 重设域管理员密码-window server 2008 R2
  18. iOS 10 的一个重要更新-开发 iMessage 的第三方插件
  19. Shell 和Python的区别。
  20. np.identity()

热门文章

  1. vue中路由
  2. angular中处理多个异步请求的方法汇总
  3. 【tomcat】如何修改tomcat的默认项目
  4. mysql Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock’
  5. 1.4-动态路由协议OSPF②
  6. linux 运行tensorflow文件缺少_bz2问题及解决
  7. 设置默认訪问项目的client的浏览器版本号(IE版本号)
  8. 新浪微博开放平台之OAuth2.0认证
  9. error: &amp;#39;Can&amp;#39;t connect to local MySQL server through socket &amp;#39;/var/lib/mysql/mysql.sock&amp;#39; (2)&amp;#39;
  10. react 使用