黑马程序员十次方微服务项目开发实践,JWT微服务鉴权(十七)

一、鉴权工具类

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

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.6.0</version>
        </dependency>
        <dependency>
            <groupId> org.springframework.boot </groupId>
            <artifactId> spring-boot-configuration-processor </artifactId>
            <optional> true </optional>
        </dependency>

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

@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: eknaij
    ttl: 360000

注:jwt为顶格的根节点

二、管理员登陆后台签发token

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

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

(2)修改AdminController的login方法

		@Autowired
		private JwtUtil jwtUtil;
	/**
	 * 管理员登录
	 * @param loginMap
	 * @return
	 */
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public Result login(@RequestBody Map<String,String> loginMap){
		Admin admin = adminService.findByLoginnameAndPassword(loginMap.get("loginname"), loginMap.get("password"));
		if(admin!=null){
			//生成token
			String token = jwtUtil.createJWT(admin.getId(), admin.getLoginname(), "admin");
			Map map=new HashMap();
			map.put("token",token);
			map.put("name",admin.getLoginname());//登陆名
			return new Result(true,StatusCode.OK,"登陆成功",map);
		}else{
			return new Result(false,StatusCode.LOGINERROE,"用户名或密码错误",null);
		}
	}

测试运行结果:
黑马程序员十次方微服务项目开发实践,JWT微服务鉴权(十七)_第1张图片

三、删除用户功能鉴权

需求:删除用户,必须拥有管理员权限,否则不能删除。
前后端约定:前端请求微服务时需要添加头信息Authorization ,内容为Bearer+空格+token
(1)修改UserController的delete方法 ,判断请求中的头信息,提取token并验证权限。

	@Autowired
	private HttpServletRequest request;
	@Autowired
	private JwtUtil jwtUtil;
	
	/**
	 * 删除
	 * @param id
	 */
	@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,"权限不足",null);
		}
		if(!authHeader.startsWith("Bearer ")){
			return new Result(false,StatusCode.ACCESSERROR,"权限不足",null);
		}
		String token=authHeader.substring(7);//提取token
		Claims claims = jwtUtil.parseJWT(token);
		if(claims==null){
			return new Result(false,StatusCode.ACCESSERROR,"权限不足",null);
		}
		if(!"admin".equals(claims.get("roles"))){
			return new Result(false,StatusCode.ACCESSERROR,"权限不足",null);
		}
		userService.deleteById(id);
		return new Result(true,StatusCode.OK,"删除成功",null);
	}

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

(1)创建拦截器类。创建 com.tensquare.user.filter.JwtFilter

@Component
public class JwtFilter extends HandlerInterceptorAdapter {
    @Autowired
    private JwtUtil jwtUtil;
    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response, Object handler) throws Exception {
        System.out.println("经过了拦截器");
        final String authHeader = request.getHeader("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            final String token = authHeader.substring(7); // The partafter "Bearer "
            Claims claims = jwtUtil.parseJWT(token);
            if (claims != null) {
                if("admin".equals(claims.get("roles"))){//如果是管理员
                    request.setAttribute("admin_claims", claims);
                }
                if("user".equals(claims.get("roles"))){//如果是用户
                    request.setAttribute("user_claims", claims);
                }
            }
        }
        return true;
    }
}

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

@Configuration
public class ApplicationConfig extends WebMvcConfigurationSupport {
    @Autowired
    private JwtFilter jwtFilter;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtFilter).
                addPathPatterns("/**").
                excludePathPatterns("/**/login");
    }
}

(3)修改UserController的delete方法

	/**
	 * 删除
	 * @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,"无权访问",null);
		}
		userService.deleteById(id);
		return new Result(true,StatusCode.OK,"删除成功",null);
	}

五、用户登录签发token

(1)修改UserController,引入JwtUtil 修改login方法 ,返回token,昵称,头像等信

	/**
	 * 用户登录
	 * @param loginMap
	 * @return
	 */
	@RequestMapping(value="/login",method=RequestMethod.POST)
	public Result login(@RequestBody Map<String,String> loginMap){
		User user =
				userService.findByMobileAndPassword(loginMap.get("mobile"),loginMap.get("password"));
		if(user!=null){
			String token = jwtUtil.createJWT(user.getId(), user.getNickname(), "user");//签发token
			Map map=new HashMap();
			map.put("token",token);
			map.put("name",user.getNickname());//昵称
			map.put("avatar",user.getAvatar());//头像
			return new Result(true,StatusCode.OK,"登陆成功",map);
		}else{
			return new Result(false,StatusCode.LOGINERROE,"用户名或密码错误",null);
		}
	}

(2) 测试运行 http://localhost:9008/user/login (POST) ,结果为如下形式:

黑马程序员十次方微服务项目开发实践,JWT微服务鉴权(十七)_第2张图片
注:记得先注册(添加)一个加密过的数据

六、发布问题验证token

(1)修改tensquare_qa工程的QaApplication,增加bean

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

(2)tensquare_qa工程配置文件application.yml增加配置:

jwt:
  config:
    key: eknaij

(3)增加拦截器类 (参考上面的拦截器代码)
(4)增加配置类ApplicationConfig (参考上面的配置类代码)
(5)修改ProblemController的add方法

	@Autowired
	private HttpServletRequest request;
	/**
	 * 增加
	 * @param problem
	 */
	@RequestMapping(method=RequestMethod.POST)
	public Result add(@RequestBody Problem problem  ){
		Claims claims=(Claims)request.getAttribute("user_claims");
		if(claims==null){
			return new Result(false,StatusCode.ACCESSERROR,"无权访问",null);
		}
		problem.setUserid(claims.getId());
		problemService.add(problem);
		return new Result(true,StatusCode.OK,"增加成功",null);
	}

七、完善

安装上面的步骤完成:回答问题、 发吐槽、 发文章的相关token鉴权

你可能感兴趣的:(十次方项目)