密码加密与微服务鉴权JWT-微服务鉴权

微服务鉴权

JWT工具类编写

1)tensquare_common工程引入依赖(考虑到工具类的通用性)

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>

2)修改tensquare_common工程,创建util.JwtUtil

package util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Date;

/**
 * Created by Administrator on 2018/4/11.
 */
@ConfigurationProperties("jwt.config")
public class JwtUtil {

    private String key ;

    private long ttl ;//一个小时

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public long getTtl() {
        return ttl;
    }

    public void setTtl(long ttl) {
        this.ttl = ttl;
    }

    /**
     * 生成JWT
     *
     * @param id
     * @param subject
     * @return
     */
    public String createJWT(String id, String subject, String roles) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder().setId(id)
                .setSubject(subject)
                .setIssuedAt(now)
                .signWith(SignatureAlgorithm.HS256, key).claim("roles", roles);
        if (ttl > 0) {
            builder.setExpiration( new Date( nowMillis + ttl));
        }
        return builder.compact();
    }

    /**
     * 解析JWT
     * @param jwtStr
     * @return
     */
    public Claims parseJWT(String jwtStr){
        return  Jwts.parser()
                .setSigningKey(key)
                .parseClaimsJws(jwtStr)
                .getBody();
    }
}

3)修改tensquare_user工程的application.yml, 添加配置

jwt:
  config:
     key: youcan
     ttl: 86400000

管理员登陆后台签发token

1)配置bean .修改tensquare_user工程Application类

	@Bean
	public JwtUtil jwtUtil(){
		return new JwtUtil();
	}

2)修改AdminController的login方法

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public Result login(@RequestBody Admin admin){
		Admin adminLogin = adminService.login(admin);
		if(adminLogin==null){
			return new Result(false, StatusCode.LOGINERROR, "登录失败");
		}
		//使得前后端可以通话的操作。采用JWT来实现。
		//生成令牌
		String token = jwtUtil.createJWT(adminLogin.getId(), adminLogin.getLoginname(), "admin");
		Map<String, Object> map = new HashMap<>();
		map.put("token", token);
		map.put("role", "admin");
		return new Result(true, StatusCode.OK, "登录成功", map);
	}

测试运行结果

{
  "flag": true,
  "code": 20000,
  "message": "登陆成功",
  "data": {
    "token":
"eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5ODQzMjc1MDc4ODI5MzgzNjgiLCJzdWIiOiJ4aWF
vbWkiLCJpYXQiOjE1MjM1MjQxNTksInJvbGVzIjoiYWRtaW4iLCJleHAiOjE1MjM1MjQ1MTl9
._YF3oftRNTbq9WCD8Jg1tqcez3cSWoQiDIxMuPmp73o",
    "name":"admin"
  }
}

删除用户功能鉴权

需求:删除用户,必须拥有管理员权限,否则不能删除。
前后端约定:前端请求微服务时需要添加头信息Authorization ,内容为Bearer+空格+token;

1)修改UserController的delete方法 ,判断请求中的头信息,提取token并验证权限。

	@RequestMapping(value="/{id}",method= RequestMethod.DELETE)
	public Result delete(@PathVariable String id ){
		String authHeader = request.getHeader("Authorization");//获取头信息
		if(authHeader==null){        
			return new Result(false,StatusCode.ACCESSERROR,"权限不足");            
		}

		if(!authHeader.startsWith("Bearer ")){        
			return new Result(false,StatusCode.ACCESSERROR,"权限不足");            
		}

		String token = authHeader.substring(7);//提取token
		Claims claims = jwtUtil.parseJWT(token);
		if(claims==null){        
			return new Result(false,StatusCode.ACCESSERROR,"权限不足");            
		}
		if(!"admin".equals(claims.get("roles"))){        
			return new Result(false,StatusCode.ACCESSERROR,"权限不足");            
		}
		userService.deleteById(id);
		return new Result(true,StatusCode.OK,"删除成功");        
	}

使用拦截器方式实现token鉴权

如果我们每个方法都去写一段代码,冗余度太高,不利于维护,那如何做使我们的代码看起来更清爽呢?我们可以将这段代码放入拦截器去实现

添加拦截器

Spring为我们提供了org.springframework.web.servlet.handler.HandlerInterceptorAdapter这个适配器,承此类,可以非常方便的实现自己的拦截器。

他有三个方法分别实现:
1)预处理;
2)后处理(调用了Service并返回ModelAndView,但未进行页面渲染);
3)返回处理(已经渲染了页面);

在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

1)创建拦截器类。

创建 com.tensquare.user.interceptor.JwtInterceptor ;

package com.tensquare.user.interceptor;

import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class JwtInterceptor implements HandlerInterceptor{
    @Autowired
    private JwtUtil jwtUtil;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("经过了拦截器");
        return true;
    }
}

2)配置拦截器类,创建com.tensquare.user.ApplicationConfig

package com.tensquare.user.config;

import com.tensquare.user.interceptor.JwtInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    @Autowired
    private JwtInterceptor jwtInterceptor;
    protected void addInterceptors(InterceptorRegistry registry) {
        //注册拦截器要声明拦截器对象和要拦截的请求
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/**/login/**");
    }
}

拦截器验证token

1)修改拦截器类 JwtFilter

package com.tensquare.user.interceptor;

import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import util.JwtUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class JwtInterceptor implements HandlerInterceptor{
    @Autowired
    private JwtUtil jwtUtil;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("经过了拦截器");
        //无论如何都放行。具体能不能操作还是在具体的操作中去判断。
        //拦截器只是负责把头请求头中包含token的令牌进行一个解析验证。
        String header = request.getHeader("Authorization");

        if(header!=null && !"".equals(header)){
            //如果有包含有Authorization头信息,就对其进行解析
            if(header.startsWith("Bearer ")){
                //得到token
                String token = header.substring(7);
                //对令牌进行验证
                try {
                    Claims claims = jwtUtil.parseJWT(token);
                    String roles = (String) claims.get("roles");
                    if(roles!=null && roles.equals("admin")){           // 如果是管理员
                        request.setAttribute("claims_admin", token);
                    }
                    if(roles!=null && roles.equals("user")){            // 如果是用户
                        request.setAttribute("claims_user", token);
                    }
                }catch (Exception e){
                    throw new RuntimeException("令牌不正确!");
                }
            }
        }
        return true;
    }
}

2)修改UserController的delete方法

	/**
	 * 删除 必须有admin角色才能删除
	 * @param id
	 */
	@RequestMapping(value="/{id}",method= RequestMethod.DELETE)
	public Result delete(@PathVariable String id ){
		Claims claims=(Claims) request.getAttribute("admin_claims");
		if(claims==null){        
			return new Result(true,StatusCode.ACCESSERROR,"无权访问");
		}
		userService.deleteById(id);
		return new Result(true,StatusCode.OK,"删除成功");
	}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值