存储登陆状态
user.js_Login中成功储存token
localStorage.setItem("jwt_token", resp.token);
login页面检查
const jwt_token = localStorage.getItem("jwt_token");
if (jwt_token) {
store.commit("updateToken", jwt_token);
store.dispatch("getinfo", {
success() {
router.push({ name: "home" });
store.commit("updatePullingInfo", false);
},
error() {
store.commit("updatePullingInfo", false);
}
})
} else {
store.commit("updatePullingInfo", false);
}
定义pullingInfo来处理跳转页面的闪问题
获取用户信息
@Autowired
private InfoService infoService;
@GetMapping("/api/user/account/info/")
public Map<String,String> getinfo(){
return infoService.getinfo();
}
传过来的token controller不需要处理
前端
headers:{
Authorization:"Bearer "+store.state.token,//这里直接调用本页面的token就可以了
}
router.js
export default new Router({
mode: 'history', //路由模式,取值为history与hash
base: '/', //打包路径,默认为/,可以修改
routes: [
{
path: string, //路径
ccomponent: Component; //页面组件
name: string; // 命名路由-路由名称
components: { [name: string]: Component }; // 命名视图组件
redirect: string | Location | Function; // 重定向
props: boolean | string | Function; // 路由组件传递参数
alias: string | Array<string>; // 路由别名
children: Array<RouteConfig>; // 嵌套子路由
// 路由单独钩子
beforeEnter?: (to: Route, from: Route, next: Function) => void;
meta: any; // 自定义标签属性,比如:是否需要登录
icon: any; // 图标
// 2.6.0+
caseSensitive: boolean; // 匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions: Object; // 编译正则的选项
}
]
})
前端实现
通过router跳转到某个界面时
必须是登录状态
router/修改
path: '/record/:recordId/',
name: "record_content",
component: RecordContentView,
meta: {
requestAuth: true,
}
router定于
router.beforeEach((to, from, next) => {//当我们通过router进入某个页面之前 会调用这个函数
if (to.meta.requestAuth && !store.state.user.is_login) {
next({ name: "user_account_login" });
} else {
next();
}
})
重定向到404
{
path: '/:catchAll(.*)',
redirect: "/404/"//重定向不用管他
}
总结
api RestController
注册/登录 PostMapper
weakKeyException
jwt密钥太短
访问非放行api
url: "https://app2676.acapp.acwing.com.cn/api/ranklist/getlist/",
type: "get",
data: {
page,
},
headers: {
Authorization: "Bearer " + store.state.user.token,
},
登录前端
const login = () => {
store.dispatch("login", {
username: username.value,
password: password.value,
success() {
store.commit("updatelogin", true);
router.push({ name: "home" });
},
error() {
console.log(store.state.user.token);
error_message.value = "用户名或者密码错误";
}
})
}在action里边写login是因为需要登录属于异步
不需要立刻执行 register却写到了页面里边
我觉得是可以写在页面里的
user.js
里边存储登录之后的jwt_token
:api `
和
localStorage.removeItem(“jwt_token”);`
Controller
Login
因为是需要传递密码 所以需要PostMapper
@RestController
public class LoginController {
@Autowired
private LoginService loginService;//我们实现是LoginServiceImpl但是引用的LoginService
@GetMapping("/login/account/token/")
public Map<String,String> getToken(@RequestParam Map<String,String> data){
String username=data.get("username");
String password=data.get("password");
return loginService.getToken(username,password);
}
}
注
public class UserDetailsImpl implements UserDetails
{
private User user; @标记点1
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {return null;}
@Override
public String getPassword() {return user.getPassword();}
@Override
public String getUsername() {return user.getUsername();}
@Override
public boolean isAccountNonExpired() {return true;}
@Override
public boolean isAccountNonLocked() {return true;}
@Override
public boolean isCredentialsNonExpired() {return true;}
@Override
public boolean isEnabled() {return true;}
}
ServiceImpl接口实现
login
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Map<String, String> getToken(String username, String password) {
UsernamePasswordAuthenticationToken authenticationToken=
new UsernamePasswordAuthenticationToken(username,password);//用户名密码身份验证令牌
Authentication authenticate = //认证类 身份验证管理器.证实(令牌)
authenticationManager.authenticate(authenticationToken);//如果登录失败 会自动处理
UserDetailsImpl loginUser=(UserDetailsImpl) authenticate.getPrincipal();
User user=loginUser.getUser();//这个getUser我们没有实现 是自动生成的 @标记点1 处get+定义的变量名
String jwt= JwtUtil.createJWT(user.getId().toString());//我们配置的jwt
Map<String,String> map=new HashMap<>();
map.put("error_message","success");
map.put("token",jwt);
return map;////根据用户名 密码 创建一个令牌 用身份验证管理器证实令牌
register
@Autowired
private UserMapper userMapper;
@Autowired
private PasswordEncoder passwordEncoder;
这里有很多判断 太长了没有写 例如密码长度/用户名长度/是否相同/
如果不判断会导致程序异常 网站崩溃
username=username.trim();//用来清空字符串两端的空格
数据库中定义长度为1000 varchar 但是约束密码为100因为需要加密
QueryWrapper<User> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("username",username);
List<User> users=userMapper.selectList(queryWrapper);//查询是否相同的用户
if(!users.isEmpty()){
map.put("error_message","用户已存在");
return map;
}
String encodedPassword= passwordEncoder.encode(password);
String photo="";
User user=new User(null,username,encodedPassword,photo);
userMapper.insert(user);
map.put("error_message","success");
Service定义接口
定义接口的时候 有利于考虑需要传那些参数 哪些返回类型
login
public Map<String,String> getToken(String username,String password);
应为登录之后需要放回数据 可能登录的时候会有用户名输错的情况
这里放回Map
登陆的实质是从后端获取token 所以登录函数为getToken
返回errormessage
register
public Map<String,String> register(String username,String password,String confirmedPassword);
现在还没有关于名称规则
把几个习俗留下来
函数名没有大写
变量名首字母小写并且驼峰
类名必定首字母大写并且驼峰命名法//这样注入的时候 自动生成变量 为首字母小写的变量容易区分
接口Service结尾 实现ServiceImpl结尾
软件包
关于官方接口的实现 Impl里创建utils放进去
不知道放那个地方的放进 utils里边//表明暂时不知道
Config 用来存放一些 配置类 //SecurityConfig
前端
meta 存放源信息
Service和Service.Impl里内容完全一致 都有Admin软件包
这样可以区分 一个是实现 一个是接口
跨域问题
告诉浏览器 后端允许跨域访问/针对浏览器安全机制
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class CorsConfig implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
String origin = request.getHeader("Origin");
if(origin!=null) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
String headers = request.getHeader("Access-Control-Request-Headers");
if(headers!=null) {
response.setHeader("Access-Control-Allow-Headers", headers);
response.setHeader("Access-Control-Expose-Headers", headers);
}
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}