ylbtech-Java-Class-@I:java.annotation.Resource
1.返回顶部
 
2.返回顶部
1.1、
import javax.annotation.Resource;
1.2、
package com.ylbtech.api.platform.controller.auth;

import com.ylbtech.api.platform.core.jwt.JwtConfigurationProperties;
import com.ylbtech.api.platform.core.jwt.JwtUtil;
import com.ylbtech.api.platform.core.response.Result;
import com.ylbtech.api.platform.core.response.ResultGenerator;
import com.ylbtech.edu.organization.domain.Organization;
import com.ylbtech.edu.organization.service.IOrganizationService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; @Slf4j
@Api(value = "账户接口")
@Validated
@RestController
@RequestMapping("/user")
public class AuthController { @Resource
private JwtUtil jwtUtil; @Autowired
private IOrganizationService organizationService; /**
* showdoc
* @catalog 用户
* @title 账户注销
* @description 账户注销接口
* @method Delete
* @url https://ip:port/user/token/logout
* @param adminID 必选 string 账号
* @return {"code":200}
* @remark
*/
@ApiOperation(value = "账户注销")
@PostMapping("/token/logout")
public Result logout(@ApiParam(required = true) @RequestBody OrganizationAdmin organizationAdmin) { if (organizationAdmin.getAdminID() == null || organizationAdmin.getAdminID().equalsIgnoreCase("")) {
return ResultGenerator.genFailedResult("adminID is null");
}
this.jwtUtil.invalidRedisToken(organizationAdmin.getAdminID());
return ResultGenerator.genOkResult();
}
}
1.3、
3.返回顶部
 
4.返回顶部
1、
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/ package javax.annotation; import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*; /**
* The Resource annotation marks a resource that is needed
* by the application. This annotation may be applied to an
* application component class, or to fields or methods of the
* component class. When the annotation is applied to a
* field or method, the container will inject an instance
* of the requested resource into the application component
* when the component is initialized. If the annotation is
* applied to the component class, the annotation declares a
* resource that the application will look up at runtime. <p>
*
* Even though this annotation is not marked Inherited, deployment
* tools are required to examine all superclasses of any component
* class to discover all uses of this annotation in all superclasses.
* All such annotation instances specify resources that are needed
* by the application component. Note that this annotation may
* appear on private fields and methods of superclasses; the container
* is required to perform injection in these cases as well.
*
* @since Common Annotations 1.0
*/
@Target({TYPE, FIELD, METHOD})
@Retention(RUNTIME)
public @interface Resource {
/**
* The JNDI name of the resource. For field annotations,
* the default is the field name. For method annotations,
* the default is the JavaBeans property name corresponding
* to the method. For class annotations, there is no default
* and this must be specified.
*/
String name() default ""; /**
* The name of the resource that the reference points to. It can
* link to any compatible resource using the global JNDI names.
*
* @since Common Annotations 1.1
*/ String lookup() default ""; /**
* The Java type of the resource. For field annotations,
* the default is the type of the field. For method annotations,
* the default is the type of the JavaBeans property.
* For class annotations, there is no default and this must be
* specified.
*/
Class<?> type() default java.lang.Object.class; /**
* The two possible authentication types for a resource.
*/
enum AuthenticationType {
CONTAINER,
APPLICATION
} /**
* The authentication type to use for this resource.
* This may be specified for resources representing a
* connection factory of any supported type, and must
* not be specified for resources of other types.
*/
AuthenticationType authenticationType() default AuthenticationType.CONTAINER; /**
* Indicates whether this resource can be shared between
* this component and other components.
* This may be specified for resources representing a
* connection factory of any supported type, and must
* not be specified for resources of other types.
*/
boolean shareable() default true; /**
* A product specific name that this resource should be mapped to.
* The name of this resource, as defined by the <code>name</code>
* element or defaulted, is a name that is local to the application
* component using the resource. (It's a name in the JNDI
* <code>java:comp/env</code> namespace.) Many application servers
* provide a way to map these local names to names of resources
* known to the application server. This mapped name is often a
* <i>global</i> JNDI name, but may be a name of any form. <p>
*
* Application servers are not required to support any particular
* form or type of mapped name, nor the ability to use mapped names.
* The mapped name is product-dependent and often installation-dependent.
* No use of a mapped name is portable.
*/
String mappedName() default ""; /**
* Description of this resource. The description is expected
* to be in the default language of the system on which the
* application is deployed. The description can be presented
* to the Deployer to help in choosing the correct resource.
*/
String description() default "";
}
2、
5.返回顶部
1、JwtUtil.java
package com.ylbtech.api.platform.core.jwt;

import com.ylbtech.api.platform.core.rsa.RsaUtils;
import com.ylbtech.api.platform.util.RedisUtils;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.Collectors; /**
* Json web token 工具 验证、生成 token
*/
@Slf4j
@Component
public class JwtUtil {
@Resource
private RedisUtils redisUtils;
@Resource
private RsaUtils rsaUtils;
@Resource
private JwtConfigurationProperties jwtProperties; private Claims getClaims(final String token) {
final Jws<Claims> jws = this.parseToken(token);
return jws == null ? null : jws.getBody();
} /**
* 根据 token 得到账户名
*/
public String getName(final String token) {
final Claims claims = this.getClaims(token);
return claims == null ? null : claims.getSubject();
} /**
* 签发 token
*
* @param name 账户名
* @param grantedAuthorities 账户权限信息[ADMIN, TEST, ...]
*/
public String sign(
final String name, final Collection<? extends GrantedAuthority> grantedAuthorities) {
// 函数式创建 token,避免重复书写
final Supplier<String> createToken = () -> this.createToken(name, grantedAuthorities);
// 看看缓存有没有账户token
final String token = (String) this.redisUtils.getValue(name);
// 没有登录过
if (StringUtils.isBlank(token)) {
return createToken.get();
}
final boolean isValidate = (boolean) this.redisUtils.getValue(token);
// 有 token,仍有效,将 token 置为无效,并重新签发(防止 token 被利用)
if (isValidate) {
this.invalidRedisToken(name);
}
// 重新签发
return createToken.get();
} /**
* 清除账户在 Redis 中缓存的 token
*
* @param name 账户名
*/
public void invalidRedisToken(final String name) {
// 将 token 设置为无效
final String token = (String) this.redisUtils.getValue(name);
Optional.ofNullable(token).ifPresent(_token -> this.redisUtils.setValue(_token, false));
} /**
* 从请求头或请求参数中获取 token
*/
public String getTokenFromRequest(final HttpServletRequest httpRequest) {
final String header = this.jwtProperties.getHeader();
final String token = httpRequest.getHeader(header);
return StringUtils.isNotBlank(token) ? token : httpRequest.getParameter(header);
} /**
* 返回账户认证
*/
public UsernamePasswordAuthenticationToken getAuthentication(
final String name, final String token) {
// 解析 token 的 payload
final Claims claims = this.getClaims(token);
// 因为 JwtAuthenticationFilter 拦截器已经检查过 token 有效,所以可以忽略 get 空指针提示
assert claims != null;
final String claimKeyAuth = this.jwtProperties.getClaimKeyAuth();
// 账户角色列表
final List<String> authList = Arrays.asList(claims.get(claimKeyAuth).toString().split(","));
// 将元素转换为 GrantedAuthority 接口集合
final Collection<? extends GrantedAuthority> authorities =
authList.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
final User user = new User(name, "", authorities);
return new UsernamePasswordAuthenticationToken(user, null, authorities);
} /**
* 验证 token 是否正确
*/
public boolean validateToken(final String token) {
boolean isValidate = true;
final Object redisTokenValidate = this.redisUtils.getValue(token);
// 可能 redis 部署出现了问题
// 或者清空了缓存导致 token 键不存在
if (redisTokenValidate != null) {
isValidate = (boolean) redisTokenValidate;
}
// 能正确解析 token,并且 redis 中缓存的 token 也是有效的
return this.parseToken(token) != null && isValidate;
} /**
* 生成 token
*/
private String createToken(
final String name, final Collection<? extends GrantedAuthority> grantedAuthorities) {
// 获取账户的角色字符串,如 USER,ADMIN
final String authorities =
grantedAuthorities
.stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
log.debug("==> user<{}> authorities: {}", name, authorities); // 过期时间
final Duration expireTime = this.jwtProperties.getExpireTime();
// 当前时间 + 有效时长
final Date expireDate = new Date(System.currentTimeMillis() + expireTime.toMillis());
// 创建 token,比如 "Bearer abc1234"
final String token =
this.jwtProperties.getTokenType()
+ " "
+ Jwts.builder()
// 设置账户名
.setSubject(name)
// 添加权限属性
.claim(this.jwtProperties.getClaimKeyAuth(), authorities)
// 设置失效时间
.setExpiration(expireDate)
// 私钥加密生成签名
.signWith(SignatureAlgorithm.RS256, this.rsaUtils.loadPrivateKey())
// 使用LZ77算法与哈夫曼编码结合的压缩算法进行压缩
.compressWith(CompressionCodecs.DEFLATE)
.compact();
// 保存账户 token
// 因为账户注销后 JWT 本身只要没过期就仍然有效,所以只能通过 redis 缓存来校验有无效
// 校验时只要 redis 中的 token 无效即可(JWT 本身可以校验有无过期,而 redis 过期即被删除了)
// true 有效
this.redisUtils.setValue(token, true, expireTime);
// redis 过期时间和 JWT 的一致
this.redisUtils.setValue(name, token, expireTime);
log.debug("==> Redis set uid<{}> token: {}", name, token);
return token;
} /**
* 解析 token
*/
private Jws<Claims> parseToken(final String token) {
try {
return Jwts.parser()
// 公钥解密
.setSigningKey(this.rsaUtils.loadPublicKey())
.parseClaimsJws(token.replace(this.jwtProperties.getTokenType(), ""));
} catch (final SignatureException e) {
// 签名异常
log.debug("Invalid JWT signature");
} catch (final MalformedJwtException e) {
// 格式错误
log.debug("Invalid JWT token");
} catch (final ExpiredJwtException e) {
// 过期
log.debug("Expired JWT token");
} catch (final UnsupportedJwtException e) {
// 不支持该JWT
log.debug("Unsupported JWT token");
} catch (final IllegalArgumentException e) {
// 参数错误异常
log.debug("JWT token compact of handler are invalid");
}
return null;
}
}

JwtUtil.java

2、
 
6.返回顶部
 
作者:ylbtech
出处:http://ylbtech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

Java-Class-@I:java.annotation.Resource的更多相关文章

  1. Java总结篇:Java多线程

    Java总结篇系列:Java多线程 多线程作为Java中很重要的一个知识点,在此还是有必要总结一下的. 一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: ...

  2. 转 Java虚拟机5:Java垃圾回收(GC)机制详解

    转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...

  3. Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    目录 引言 四种线程池 newCachedThreadPool:可缓存的线程池 newFixedThreadPool:定长线程池 newSingleThreadExecutor:单线程线程池 newS ...

  4. Java虚拟机2:Java内存区域

    1.几个计算机的概念 为以后写文章考虑,也为巩固自己的知识和一些基本概念,这里要理清楚几个计算机中的概念. 1.计算机存储单位 从小到大依次为位Bit.字节Byte.千字节KB.兆M.千兆GB.TB, ...

  5. Java调用本地接口:java.lang.UnsatisfiedLinkError

    Java调用本地接口:java.lang.UnsatisfiedLinkError 我的问题不在这篇文章描述中, 而是因为jni原来是c实现, 现在切换到cpp了, 需要在对应的cpp文件中加入ext ...

  6. Java基础16:Java多线程基础最全总结

    Java基础16:Java多线程基础最全总结 Java中的线程 Java之父对线程的定义是: 线程是一个独立执行的调用序列,同一个进程的线程在同一时刻共享一些系统资源(比如文件句柄等)也能访问同一个进 ...

  7. Java基础教程:Java内存区域

    Java基础教程:Java内存区域 运行时数据区域 Java虚拟机在执行Java程序的过程种会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟 ...

  8. jsp(java server pages):java服务器端的页面

    jsp(java server pages):java服务器端的页面 JSP的执行过程1.浏览器输入一个jsp页面2.tomcat会接受*.jsp请求,将该请求发送到org.apache.jasper ...

  9. JAVA基础语法:java编程规范和常用数据类型(转载)

    JAVA基础语法:java编程规范和常用数据类型 摘要 本文主要介绍了最基本的java程序规则,和常用数据类型,其中侧重说了数组的一些操作. 面向java编程 java是纯面向对象语言,所有的程序都要 ...

  10. JAVA提高五:注解Annotation

    今天我们学习JDK5.0中一个非常重要的特性,叫做注解.是现在非常流行的一种方式,可以说因为配置XML 比较麻烦或者比容易查找出错误,现在越来越多的框架开始支持注解方式,比如注明的Spring 框架, ...

随机推荐

  1. ASP.NET Error Handling

    https://docs.microsoft.com/en-us/aspnet/web-forms/overview/getting-started/getting-started-with-aspn ...

  2. 6个实例详解如何把if-else代码重构成高质量代码

    本文提纲: 为什么我们写的代码都是if-else?这样的代码有什么缺点?是否有优化的方法?如何重构?异常逻辑处理型重构方法状态处理型重构方法为什么我们写的代码都是if-else?程序员想必都经历过这样 ...

  3. RFC6241 NETCONF

    概述 NETCONF = The Network Configuration Protocol SDN = Software Define Network NETCONF协议分为传输层.消息层.操作层 ...

  4. 【转】JMX之ObjectName

    原文链接:https://blog.csdn.net/yunlong34574/article/details/46563187 ObjectName 就是存储了一个domain(域)下的一些属性,属 ...

  5. The request with exception: The SSL connection could not be established, see inner exception. requestId 解决方案

    DOTNET CORE 部署 Centos7 抛出异常 环境变量如下: .NET Core SDK (reflecting any global.json): Version: 2.2.401 Com ...

  6. 04 循环结构概述和for语句的格式及其使用

    04.01_Java语言基础(循环结构概述和for语句的格式及其使用) A:循环结构的分类 for,while,do…while B:循环结构for语句的格式: for(初始化表达式;条件表达式;循环 ...

  7. vue-cesium中经纬度写反了,报错

    vue-cesium中经纬度写反了,报错 [Vue warn]: Invalid prop: custom validator check failed for prop "position ...

  8. UVA

    A network is composed of N computers connected by N - 1 communication links such that any two comput ...

  9. Django Model里的__str__以及Meta

    举个栗子,注释已经比较详细了 name = models.CharField(max_length=30,verbose_name='标签名称') #max_length=30里的30在mysql以前 ...

  10. mac 密码重置

    首先请开机或重新启动系统,在电脑刚启动时,请按下键盘上的 command+S 组合键不动, 接下来会在屏幕上看到一串串的命令字符显示,当进入安全模式以后,会看到 一个 root 开始的命令行输入端口. ...