jwt,spring security ,feign,zuul,eureka 前后端分离 整合 实现 简单 权限管理系统 与 用户认证的实现
本例子 包含有 一下模块:eureka 模块,充当 注册中心角色user-service-api 客户端接口和实体user-service-provider 客户端服务提供者user-conusmer 客户端消费者zuul 模块为网关,用来实现统一路由与 存放 前端静态资源security-config spring security客户公共的实现认证...
本例子 包含有 一下模块:
eureka 模块,充当 注册中心角色
user-service-api 客户端接口和实体
user-service-provider 客户端服务提供者
user-conusmer 客户端消费者
zuul 模块为网关,用来实现统一路由与 存放 前端静态资源
security-config spring security客户公共的实现
认证逻辑的实现:
首先 zuul 模块下 的 login.html 登录页面 输入用户名密码后,点击 登录 后就会触发 一下代码
$("#loginBtn").click(function(){
$.ajax({
url:"/user-consumer/login",
type:"POST",
dataType:"json",
async:false,
contentType:"application/json;charset=utf-8",
data: JSON.stringify({userName:$("#userName").val(),password:$("#password").val(),}),
success:function(message){
console.log(".....................");
console.log(message=="ok");
console.log(message);
if(message.result=="ok"){
console.log(message);
window.location.href="/main.html";
}else{
console.log(message);
}
},
error:function(message){
console.log(".....................");
console.log(message);;
}
});
});
点击登录 按钮,就会 由zuul 网关,路由到 user-consumer服务的 /login , 当 请求 路由到 user-consumer时 就会被
spring security 的 JwtUsernamePasswordAuthenticationFilter 过滤器拦截,此时就会执行如下代码
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse rsp)
throws AuthenticationException {
try {
User user = new ObjectMapper().readValue(req.getInputStream(),User.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
user.getUserName(),
user.getPassword(),
new ArrayList<>())
);
}catch (Exception e){
e.printStackTrace();
}
return null;
}
把用户名 和 密码 保证成 token , 供 自定义 的 provider 使用,下面是 自定义 provider 的核心代码
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
if(userDetails!=null){
if(bCryptPasswordEncoder.matches(password,userDetails.getPassword())){
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
Authentication auth = new UsernamePasswordAuthenticationToken(name,password,authorities);
return auth;
}
}
return null;
}
自定义 的 provider 将 认证 用户的 凭证,认证 成功 后 将 执行 JwtUsernamePasswordAuthenticationFilter的
successfulAuthentication 生成 token,返回给浏览器,以后浏览器每次请求都要携带该token,
一下 是 successfulAuthentication 的代码
@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse rsp, FilterChain chain,
Authentication auth) {
Map<String,Object> map = new HashMap<>();
map.put("username",auth.getName());
map.put("authorities",auth.getAuthorities().stream()
.map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
String token = JwtTokenUtils.generatorToken(map);
rsp.addHeader("Set-Cookie",
"access_token="+token+";Path=/;HttpOnly");
try {
rsp.getWriter().write("{\"result\":\"ok\"}");
} catch (IOException e) {
e.printStackTrace();
}
}
每次 请求 都需要经过 JwtTokenAuthenticationFilter 过滤器,对token 进行解析
一下是 JwtTokenAuthenticationFilter 的核心代码
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token= CookieUtil.getCookieValue(request,ACCESS_TOKEN);
if(token!=null){
try{
Claims claims= JwtTokenUtils.phaseToken(token);
String username = claims.get("username").toString();
List<String> authorities = claims.get("authorities", List.class);
if (username != null) {
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(username, null,
authorities.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
SecurityContextHolder.getContext().setAuthentication(auth);
}
}catch (Exception e){
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("{\"code\":\"-1\",\"msg\":\"error\"}");
}
}
filterChain.doFilter(request, response);
}
代码 例子 https://gitee.com/shenduedu/base_spring_cloud.git
更多推荐
所有评论(0)