这篇文章是建立在第一篇,spring boot住在jpa, swagger2, loggin,第二篇,springboot集成redis缓存基础上的,这里主要介绍如何使用jwt & spring-boot-starter-security实现api的保护。
RESTful资源是无状态的,但是我们写的API可能也不会是让人随意调,所以要给API加上调用权限验证,为了能更好的适用移动端、h5、或其它终端调用,我选择jwt配合spring-boot-starter-security来验证。
客户端发送用户验证信息到服务器,服务器根据用户信息生成一段加密的密文(Token),验证通过后,客户端的所有请求都在http header中附加上token。至于jwt的原理些这里就不详细介绍了,感兴趣的可以搜一搜。
下面介绍怎么在项目里进行配制,把api难使用起来。
- 添加引用
在*.gradle文件中添加jjwt和security的引用
compile ("org.springframework.boot:spring-boot-starter-security")
compile ("io.jsonwebtoken:jjwt:${jjwtVersion}")
- 在application.yml中配置jwt的一些值
#jwt
jwt:
header: Authorization
secret: yoursecret
expiration: 604800
tokenHead: "Bearer "
- 配制security适配器
package leix.lebean.sweb.common.config;
import leix.lebean.sweb.auth.secruity.AuthenticationEntryPoint;
import leix.lebean.sweb.auth.secruity.AuthenticationTokenFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
/**
* Name:WebSecurityConfig
* Description:
* Author:leix
* Time: 2017/6/12 10:06
*/
@SuppressWarnings("SpringJavaAutowiringInspection")
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationEntryPoint unauthorizedHandler;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.userDetailsService(this.userDetailsService)
.passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
return new AuthenticationTokenFilter();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.POST, "/users")
.antMatchers("/", "/auth/**", "/resources/**", "/static/**", "/public/**", "/webui/**", "/h2-console/**"
, "/configuration/**", "/swagger-ui/**", "/swagger-resources/**", "/api-docs", "/api-docs/**", "/v2/api-docs/**"
, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.gif", "/**/*.svg", "/**/*.ico", "/**/*.ttf", "/**/*.woff");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// 由于使用的是JWT,我们这里不需要csrf
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
// 允许对于网站静态资源的无授权访问
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated();
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// 禁用缓存
httpSecurity.headers().cacheControl();
}
}
- 新建一个auth的业务模块
创建与验证业务相关的模块auth,并在auth中实现用户的验证、token的刷新。
AuthController
package leix.lebean.sweb.auth;
/**
* Name:AuthController
* Description:用户认证接口
* Author:leix
* Time: 2017/6/12 09:42
*/
@RestController
@Api(value = "认证服务", description = "与用户认证相关的服务", position = 1)
public class AuthController extends BaseController {
@Value("${jwt.header}")
private String tokenHeader;
@Autowired
IAuthService authService;
@PostMapping("/auth")
@ApiOperation(value = "用户认证", notes = "用户信息认证服务,用户登录名与密码,返回验证结果")
@ApiImplicitParam(name = "authentication", value = "用户登录信息", dataType = "Authentication")
public ResponseEntity<AuthenticationResponse> auth(@RequestBody Authentication authentication) {
String token = authService.login(authentication.getName(), authentication.getPassword());
return ResponseEntity.ok(new AuthenticationResponse(token));
}
@GetMapping("/auth")
@ApiOperation(value = "刷新TOKEN", notes = "刷新用户Token服务")
public ResponseEntity<AuthenticationResponse> refreshAndGetAuthenticationToken(
HttpServletRequest request) throws AuthenticationException {
String token = request.getHeader(tokenHeader);
String refreshedToken = authService.refresh(token);
if (refreshedToken == null) {
return ResponseEntity.badRequest().body(null);
} else {
return ResponseEntity.ok(new AuthenticationResponse(refreshedToken));
}
}
}
详细代码来看这里看这里吧!源码@github