如今前后端分离技术用的相当多,那么肯定会用到认证和授权的内容。
尝试使用SpringBoot结合SpringSecurity做后端,Vue做前端,但是首发不利。。。遇到艰难险阻,下面记录一下:
由于细节不重要,包括UserDetails等接口的实现啊什么的!我们主要看配置类
SecurityConfig配置类
package com.wanna.usermsg.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wanna.usermsg.bean.MyUserDetails;
import com.wanna.usermsg.service.MyUserDetailsService;
import com.wanna.usermsg.util.MyPasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
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.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.crypto.bcrypt.BCryptPasswordEncoder;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
@Configuration //标识此类为配置类
@EnableWebSecurity //启动SpringSecurity过滤器链
public class SecurityConfig extends WebSecurityConfigurerAdapter { //继承WebSecurityConfigurerAdapter
@Autowired
MyUserDetails myUserDetails;
@Autowired
MyUserDetailsService myUserDetailsService;
@Autowired
MyPasswordEncoder myPasswordEncoder;
@Autowired
ObjectMapper objectMapper;
@Override
protected void configure(HttpSecurity http) throws Exception { //登录配置
http.authorizeRequests() //发出一个请求拦截
.antMatchers("/addUser").hasAuthority("admin") //有这些权限的可以访问/addUser
.antMatchers("/delUser").hasAuthority("admin") //有这些权限的可以访问/delUser
.antMatchers("/updUser").hasAuthority("admin") //有这些权限的可以访问/updUser
.antMatchers("/queryUser").hasAuthority("user") //有这些权限的可以访问/queryUser
.antMatchers("/loginHome").permitAll() //登录页允许所有人访问
.antMatchers("/**") //拦截表达式
.fullyAuthenticated() //认证拦截
.and()
.httpBasic() //以httpBasic的方法进行登录
.and()
.formLogin() //使用表单的方式进行登录
.loginPage("/loginHome") //自定义登录页面
.successHandler((request,response,authentication)->{ //执行成功的处理方法
Map<String,Object> map = new HashMap<String,Object>();
map.put("code",200);
map.put("message","登录成功");
map.put("data",authentication);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
out.write(objectMapper.writeValueAsString(map));
out.flush();
out.close();
})
.and()
.cors().disable() //关闭跨域拦截
.csrf().disable(); //关闭跨站拦截
}
@Override
public void configure(WebSecurity web) throws Exception { //设置拦截
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
//对于在header里面增加token等类似情况,放行所有OPTIONS请求。
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //用户认证
/**
* 在内存中配置两个用户wanna、baby
* wanna的角色是admin、baby的角色是user
* wanna的密码为123456、baby的密码是111111
*/
// auth.inMemoryAuthentication() //在内存中配置了两个用户wanna、baby
// .withUser("wanna").roles("admin").password("123456")
// .and()
// .withUser("baby").roles("user").password("111111");
auth.inMemoryAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.withUser("wanna")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("admin")
.authorities("admin")
.and()
.withUser("baby")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles("user")
.authorities("user");
}
}
在浏览器中,使用wanna(username)+123456(password),完全正常,并且成功返回了json数据。

正当我兴奋之时,想要在Vue中简单的访问:
axios.post("http://127.0.0.1:8081/loginHome"?username=wanna&password=123456").then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err);
})
结果。。。

人无了呀!!!尝试用postman测试(百度,这是一个很不错的接口测试软件)

成功???wtf???
看来应该是我Vue的设置问题了,我第一时间想到的就是跨域问题。因此,我上百度搜索Vue跨域设置。。。。然后我看到那些教程的跨域都是Vue2.x的,,都是设置vue.config.js啊什么的,Emm,我现在用的是Vue4.x,目录结构似乎没有这个文件,我继续翻教程,成功找到了官网对于vue.config.js文件的描述的链接。官网是这样说的:

原来vue.config.js文件会被vuecli自动加载!怪不得网上的教程都是让你建个文件就行!
我赶紧建立好文件vue.config.js,并且仿照网上的教程写了配置文件:
module.exports = {
devServer: {
host: 'localhost', //设置主机名
port: '8080', // 设置dev服务器占用的端口号
https: false, // https: {type:Bollean}
open: true, // 配置自动启动浏览器,当启动项目,自动打开浏览器
// 配置代理
proxy: {
"/api": {
target: 'http://127.0.0.1:8081', // 想要访问接口域名
ws: true, //代理websocket
changeOrigin: true, // 开启跨域,在本地创建一个虚拟服务,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据交互就不会有问题
pathRewrite: {
"^/api": '', // 利用这个地面的值拼接上target里面的地址
}
}
}
}
}
我们发现,这是通过配置dev服务器的代理服务实现的跨域的!将target下(target是我们的服务器地址)的路径映射到本项目的/api/下,因此,我们如果要请求的是target/loginHome页面,代理之后,我们应该请求的页面是/api/loginHome。接着,我们使用control+C结束当前项目,然后使用npm run serve重新运行当前项目,这是为了让配置文件能够生效,我们使用vue继续编写下面的测试:
Axios.post("/api/loginHome?username=wanna&password=123456").then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err);
})
结果如下:

成功的返回了json数据!!!终于,还是跨域的问题,Emm
网友评论