前言
本例子是前後端分離,springboot版本是1.5.x ,資料層用的jpa,利用jsonp實作跨域,在使用jsonp時需要注意,jsonp隻能用get才能實作跨域,在使用jsonp的時候遇到了很多坑,和大家一起分享一下。
jsonp原理
JSONP是JSON with Padding的略稱。它是一個非官方的協定,它允許在伺服器端內建Script tags傳回至用戶端,通過javascript callback的形式實作跨域通路(這僅僅是JSONP簡單的實作形式)。–來源百度
package com.example.student.config;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice;
/**
* jsonp實作跨域
*/
@ControllerAdvice(basePackages = {"com.sinoyd.controller"})
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {
public JsonpAdvice() {
super("callback", "jsonp");
}
}
具體執行個體Controller層代碼
/**
* 使用jsonp形式登入
*
* @param uid
* @param pid
* @param response
* @return
*/
@RequestMapping(value = "/testJsonp/login", produces = MediaType.APPLICATION_JSON_VALUE)
public Object login(@RequestParam("userName") String userName, @RequestParam("password") String passWord, HttpServletResponse response) {
try {
Validator validator = Validator.create()
.notEmpty("使用者名", userName)
.notEmpty("密碼", passWord);
if (!validator.valid()) {
response.setStatus(ResStatus.BAD_REQUEST.getCode());
return ResEntity.failed(new ResException(validator.getMessage()), ResStatus.BAD_REQUEST);
}
// 加密方式--這個可以去掉
String passWord1= EncryptUtil.decrypt(passWord);
String userName1= EncryptUtil.decrypt(userName);
Helpers.requireNonNull("使用者名或密碼錯誤", passWord1, userName1);
User user = new User();
user.setUserName(userName1.trim());
user.setPassword(passWord1.trim());
return ResEntity.success(authService.login(user, response, true));
} catch (Exception e) {
response.setStatus(ResStatus.FAILED.getCode());
return ResEntity.failed(e);
}
}
== @RequestMapping(value = “/testJsonp/login”, produces = MediaType.APPLICATION_JSON_VALUE)==
這個一定要加上,使用jsonp前端一定要使用get方式
解決403問題的思路
403–伺服器拒絕通路,一般都是沒有權限,解決思路是:1.jsonp的調用方式 --get 2.使用jsonp後,前端無法擷取token,這個時候必須把token放在傳回值中。如果有什麼不懂的可以随時聯系我。3.如果使用了權限架構的時候記得把這個接口的路徑攔截放行。
@Configuration
@EnableWebSecurity//(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final RedisTemplate redisTemplate;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
public WebSecurityConfig(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
// 設定 HTTP 驗證規則
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers("/public/**", "/html/**", "/static/**", "/vendor/**", "/**/*.js", "/fonts/**", "/**/*.css", "/index.html", "/*.js", "/api/static/files/**").permitAll()
.antMatchers(HttpMethod.POST, "/api/auth/**").denyAll()
.antMatchers("/api/qyt/report/**").permitAll()
.antMatchers(HttpMethod.GET, "/api/auth/testJsonp/login").permitAll() //jsonp跨域路徑放行
.antMatchers("/api/qyt/notice/**").permitAll()
.antMatchers("/api/qyt/attach/**").permitAll()
.antMatchers("/api/qyt/job-test/**").permitAll()
.anyRequest().authenticated() // 所有請求需要身份認證
.and().headers().frameOptions().disable()// 禁用x-frame 、
.and()
.addFilter(new JwtTokenFilter(authenticationManager(), jwtTokenUtil)); //自定義攔截器
}
}
postman
測試成功示例:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLwMmeNdXVU1UNNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0ITOxEDMzYTMwMDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)