jwt配置 restful_spring-security-jwt Restful API Token 安全认证

介绍

自己尝试在基于 spring-boot 的 RESTFul API 的安全认证上做的调研与测试。

微服务架构是未来的趋势,但是在 API 安全认证方面的文章不多,大多数是基于 MVC 和 session 的,但是微服务时代的 API 都是无状态的,遵循 Restful( 附一篇比较好的博客介绍 RESTFul 理解 RESTful 架构 )约束。不能满足需求,所以我就推动一下,将文章弄新一点。

适合读者

Spring-boot 的 RESTFul API 安全认证,无状态,无 session

spring-data-jpa 进行用户权限存储管理,基于 MySQL,不是网上一大堆教程基于内存的用户认真

jwt 协议的 token

为什么不采用 httpBasic

由于基于 httpBasic 认证的很简单,网上教程一大堆,不做过多介绍。这里我采用的是基于 jwt 协议的 API 安全认证。

用户每次都在传输过程中传输用户名和密码,太不安全了

用户每次请求一个 url 都会访问数据库,会导致数据库的访问压力!太大了。

为什么不采用 OAuth2

OAuth2 协议也是十分优秀的,但是我还是个菜鸟,虽然理解了 OAuth2 ,实现感觉也不难,但是还米有看懂 spring-boot 的框架源码,所以在集成方面不是很顺手。

其实还有一点就是 OAuth2 相对 jwt 等来说还是相对复杂的。如果我们不对外提供提供授权服务,name 使用 OAuth 个人感觉还是相当费劲的,传输效率和模式上,都没有 jwt 等 token 来的方便。

其实,基于 token 的认证,大多数自己实现也是十分方便的,加密解密,存在 Redis 里,然后自动过期,一切都很简单,大家自己设计适合自己的认证才是最关键的。

实现

基于 MySQL 的用户认证

网上代码一大堆,其实就是继承 UserDetailsService 就行了,需要自己设计 jpa 的表,我的代码里有例子,可以随意扩展。

@Service

public class UserService implements UserDetailsService {

@Autowired

SysUserRepository sysUserRepository;

然后在 WebSecurityConfigurerAdapter 中进行配置自己的 UserDetailsService,很简单。

@EnableWebSecurity

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Bean

UserDetailsService customUserService() {

return new UserService();

}

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {

auth.userDetailsService(customUserService());

}

jwt 的 token 生成

就是 jwt 协议的 加密和解密。需要设置加密算法,加密秘钥,过期时间等。

加密的时候,把 username 加进去,讲道理应该是 userid。这样我们前端就可以使用该 id 来进行请求其他服务。

解密的时候,需要进行过期校验,秘钥校验等

class TokenAuthenticationService {

static final long EXPIRATIONTIME = 1000*60*60*24*1; // 1 days

static final String SECRET = "ThisIsASecret";

static final String TOKEN_PREFIX = "Bearer";

static final String HEADER_STRING = "Authorization";

static void addAuthentication(HttpServletResponse res, String username) {

String JWT = Jwts.builder()

.setSubject(username)

.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))

.signWith(SignatureAlgorithm.HS512, SECRET)

.compact();

res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);

}

static Authentication getAuthentication(HttpServletRequest request) {

String token = request.getHeader(HEADER_STRING);

if (token != null) {

// parse the token.

String user = Jwts.parser()

.setSigningKey(SECRET)

.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))

.getBody()

.getSubject();

return user != null ?

new UsernamePasswordAuthenticationToken(user, null, emptyList()) :

null;

}

return null;

}

}

jwt 的 filter 进行 rul 认证

这里设置 登录 只能从 post 进行,并设置了两个 filter 分别对 login 和其他 url 进行拦截。

@Override

protected void configure(HttpSecurity http) throws Exception {

http.csrf().disable().authorizeRequests()

.antMatchers("/").permitAll()

.antMatchers(HttpMethod.POST, "/login").permitAll()

.anyRequest().authenticated()

.and()

// We filter the api/login requests

.addFilterBefore(new JWTLoginFilter("/login", authenticationManager()),

UsernamePasswordAuthenticationFilter.class)

// And filter other requests to check the presence of JWT in header

.addFilterBefore(new JWTAuthenticationFilter(),

UsernamePasswordAuthenticationFilter.class);

}

如何使用

使用之前

由于我集成了 spring-data-jpa,所以在使用之前需要配置数据库,并插入一些数据。

还好,我在初始化工程的时候替你们做了。我在 init 目录中进行了初始化设置,所以会自动插入两个用户名。

@Override

public void run(String... args) throws Exception {

logger.info(">>>>>>>>>>>>>>>服务启动检查1,开始检查用户系统<<<<<<<<<<<<

if (sysUserRepository.count() != 0) {

logger.info(">>>>>>>>>>>>>>>用户已经初始化<<<<<<<<<<<<

} else {

logger.info(">>>>>>>>>>>>>>不存在初始用户,开始创建<<<<<<<<<<<<

SysRole sysRole1 = new SysRole(1L, "ROLE_ADMIN");

SysRole sysRole2 = new SysRole(2L, "ROLE_USER");

sysRoleRepository.save(Arrays.asList(sysRole1, sysRole2));

List roles1 = Arrays.asList(sysRole1);

SysUser sysUser1 = new SysUser(1L, "root", "nibudong");

sysUser1.setRoles(roles1);

List roles2 = Arrays.asList(sysRole2);

SysUser sysUser2 = new SysUser(2L, "shilei", "nicai");

sysUser2.setRoles(roles2);

sysUserRepository.save(Arrays.asList(sysUser1, sysUser2));

logger.info(">>>>>>>>>>>>>>初始用户创建结束<<<<<<<<<<<<

}

logger.info(">>>>>>>>>>>>>>>检查用户系统结束<<<<<<<<<<<<

}

如何使用

先获得 jwt 的 token

再请求 url

代码

最后

登录请求一定要使用 HTTPS,否则无论 Token 做的安全性多好密码泄露了也是白搭

你可能感兴趣的:(jwt配置,restful)