zoukankan      html  css  js  c++  java
  • Java-Class-@I:java.annotation.Resource.java

    ylbtech-Java-Class-@I:java.annotation.Resource.java
    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.返回顶部
     
    warn 作者:ylbtech
    出处:http://ylbtech.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    JSP自定义标签_用简单标签控制标签体执行10次
    JSP自定义标签_用简单标签实现控制标签体是否执行
    eclipse 使用lombok 精简java bean
    转 :关于springmvc使用拦截器
    转: spring静态注入
    spring 4.0+quartz2.2 实现持久化
    排除maven jar冲突 maven tomcat插件启动报错 filter转换异常
    转 Quartz将Job持久化所需表的说明
    转 maven jetty 插件
    ORA-14300: 分区关键字映射到超出允许的最大分区数的分区
  • 原文地址:https://www.cnblogs.com/storebook/p/11103972.html
Copyright © 2011-2022 走看看