這篇文章是建立在第一篇,spring boot住在jpa, swagger2, loggin绪钥,第二篇刀森,springboot集成redis緩存基礎(chǔ)上的,這里主要介紹如何使用jwt & spring-boot-starter-security實(shí)現(xiàn)api的保護(hù)俏讹。
RESTful資源是無(wú)狀態(tài)的当宴,但是我們寫的API可能也不會(huì)是讓人隨意調(diào)畜吊,所以要給API加上調(diào)用權(quán)限驗(yàn)證,為了能更好的適用移動(dòng)端户矢、h5玲献、或其它終端調(diào)用,我選擇jwt配合spring-boot-starter-security來(lái)驗(yàn)證。
客戶端發(fā)送用戶驗(yàn)證信息到服務(wù)器捌年,服務(wù)器根據(jù)用戶信息生成一段加密的密文(Token)瓢娜,驗(yàn)證通過后,客戶端的所有請(qǐng)求都在http header中附加上token礼预。至于jwt的原理些這里就不詳細(xì)介紹了眠砾,感興趣的可以搜一搜。
下面介紹怎么在項(xiàng)目里進(jìn)行配制托酸,把a(bǔ)pi難使用起來(lái)褒颈。
- 添加引用
在*.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()
// 允許對(duì)于網(wǎng)站靜態(tài)資源的無(wú)授權(quán)訪問
.antMatchers(
HttpMethod.GET,
"/",
"/*.html",
"/favicon.ico",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
// 除上面外的所有請(qǐng)求全部需要鑒權(quán)認(rèn)證
.anyRequest().authenticated();
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
// 禁用緩存
httpSecurity.headers().cacheControl();
}
}
- 新建一個(gè)auth的業(yè)務(wù)模塊
創(chuàng)建與驗(yàn)證業(yè)務(wù)相關(guān)的模塊auth谷丸,并在auth中實(shí)現(xiàn)用戶的驗(yàn)證、token的刷新应结。
AuthController
package leix.lebean.sweb.auth;
/**
* Name:AuthController
* Description:用戶認(rèn)證接口
* Author:leix
* Time: 2017/6/12 09:42
*/
@RestController
@Api(value = "認(rèn)證服務(wù)", description = "與用戶認(rèn)證相關(guān)的服務(wù)", position = 1)
public class AuthController extends BaseController {
@Value("${jwt.header}")
private String tokenHeader;
@Autowired
IAuthService authService;
@PostMapping("/auth")
@ApiOperation(value = "用戶認(rèn)證", notes = "用戶信息認(rèn)證服務(wù)刨疼,用戶登錄名與密碼,返回驗(yàn)證結(jié)果")
@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服務(wù)")
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));
}
}
}
詳細(xì)代碼來(lái)看這里看這里吧鹅龄!源碼@github