1JwtTokenUtils工具

2公共返回对象

3Admin实现UserDetails

4AdminLoginParam

5AdminLoginController

6SecurityConfig

7RestAuthorizationEntryPoint

8RestfulAccessDeniedHandle

9ScurityConfig(增加Swagger2配置)

10Swagger2Config

1JwtTokenUtils工具

package com.xxxx.server.config.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtTokenUtils {
    private static final String CLAIM_KEY_USERNAME="sub";
    private static final String CLAIM_KEY_CREATED="created";
    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expiration}")
    private Long expiration;

    /**
     * 创建token
     * @param userDetails
     * @return
     */
    public String generateToken(UserDetails userDetails){
        Map<String,Object> claims = new HashMap<>();
        claims.put(CLAIM_KEY_USERNAME,userDetails.getUsername());
        claims.put(CLAIM_KEY_CREATED,new Date());
        return generateToken(claims);
    }
    private String generateToken(Map<String,Object> claims){
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(generateExpirationDate())
                .signWith(SignatureAlgorithm.ES512,secret)
                .compact();
    }

    private Date generateExpirationDate() {
        return new Date(System.currentTimeMillis()+expiration*1000);
    }

    /**
     * 解析token,获取用户名
     * @param token
     * @return
     */
    public String getUserNameToken(String token){
        String username;
        try {
            Claims claims = getClaimsFormToken(token);
            username = claims.getSubject();
        }catch (Exception e){
            e.printStackTrace();
            username=null;
        }

        return username;

    }

    private Claims getClaimsFormToken(String token) {
        Claims claims=null;
        try{
            claims=Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        }catch (Exception e){
         e.printStackTrace();
        }
        return claims;
    }
    /**
     * 校驗是否真確
     * @param token
     * @param userDetails
     * @return
     */
    public boolean validateToken(String token,UserDetails userDetails){
        String username = getUserNameToken(token);
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }
    /**
     * 是否可以刷新时间
     * @param token
     * @return
     */
    public boolean canRefresh(String token){
        return !isTokenExpired(token);
    }
    /**
     * 刷新token
     * @param token
     * @return
     */
    public String refreshToken(String token){
        Claims claims = getClaimsFormToken(token);
        claims.put(CLAIM_KEY_CREATED,new Date());
        return generateToken(claims);
    }
    private boolean isTokenExpired(String token) {
        Date expireDate=getExpiredDateFromToken(token);
        return expireDate.before(new Date());
    }
    private Date getExpiredDateFromToken(String token) {
        Claims claims =getClaimsFormToken(token);
        return claims.getExpiration();
    }
}

2公共返回对象

package com.xxxx.server.pojo;

        import lombok.AllArgsConstructor;
        import lombok.Data;
        import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class RespBean {
    private long code;
    private String message;
    private Object obj;
    public static RespBean success(String message){
        return new RespBean(200,message,null);
    }

    public static RespBean success(String message,Object obj){
        return new RespBean(200,message,obj);
    }

    public static RespBean error(String message){
        return new RespBean(500,message,null);
    }
    public static RespBean error(String message,Object obj){
        return new RespBean(500,message,obj);
    }
}

3Admin实现UserDetails

package com.xxxx.server.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.Serializable;
import java.util.Collection;

/**
 * <p>
 *
 * </p>
 *
 * @author zhoubin
 * @since 2021-09-09
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_admin")
@ApiModel(value="Admin对象", description="")
public class Admin implements Serializable, UserDetails {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "姓名")
    private String name;

    @ApiModelProperty(value = "手机号码")
    private String phone;

    @ApiModelProperty(value = "住宅电话")
    private String telephone;

    @ApiModelProperty(value = "联系地址")
    private String address;

    @ApiModelProperty(value = "是否启用")
    private Boolean enabled;

    @ApiModelProperty(value = "用户名")
    private String username;

    @ApiModelProperty(value = "密码")
    private String password;

    @ApiModelProperty(value = "用户头像")
    private String userFace;

    @ApiModelProperty(value = "备注")
    private String remark;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

4AdminLoginParam

package com.xxxx.server.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value ="AdminLogin对象",description = "")
public class AdminLoginParam {
    @ApiModelProperty(value ="用户名",required =true)
    private String username;
    @ApiModelProperty(value ="密码",required = true)
    private String password;
}

5AdminLoginController

package com.xxxx.server.controller;

import com.xxxx.server.pojo.Admin;
import com.xxxx.server.pojo.AdminLoginParam;
import com.xxxx.server.pojo.RespBean;
import com.xxxx.server.service.IAdminService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;

@RestController
@Api(tags = "LoginController")
public class LoginController {
    @Autowired
    private IAdminService adminService;
    @ApiOperation(value="登录之后返回token")
    @PostMapping("/login")
    public RespBean login(AdminLoginParam adminLoginParam, HttpServletRequest httpServletRequest){
        return adminService.login(adminLoginParam.getUsername(),adminLoginParam.getPassword(),httpServletRequest);
    }
    @ApiOperation("获取当前用户信息")
    @PostMapping("/admin/info")
    public Admin getAdminINfo(Principal principal){
        if (null==principal){
            return null;
        }
        String username = principal.getName();
        Admin admin=adminService.getAdminByUserName(username);
            admin.setPassword(null);
            return admin;

    }

    @ApiOperation(value = "退出登录")
    @RequestMapping("/logout")
    public RespBean logout(){
        return RespBean.success("注销成功!");
    }
}

6SecurityConfig

package com.xxxx.server.config.security;

import com.xxxx.server.pojo.Admin;
import com.xxxx.server.service.IAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private IAdminService adminService;
    @Autowired
    private RestAuthorizationEntryPoint restAuthorizationEntryPoint;
    @Autowired
    private ResstfulAccessDeniedHandler resstfulAccessDeniedHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                //基于token,不要session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)/*
                    ALWAYS
                    总是创建HttpSession  IF_REQUIRED
                    Spring Security只会在需要时创建一个HttpSession
                    NEVER
                    Spring Security不会创建HttpSession,但如果它已经存在,将可以使用HttpSession
                    STATELESS
                    Spring Security永远不会创建HttpSession,它不会使用HttpSession来获取SecurityContext

 */
                .and()
                .authorizeRequests()
                .antMatchers("/login","/logout")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .headers()
                .cacheControl();
                //添加登录授权拦截器
        http.addFilterBefore(jwtAuthencationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
                //自定义未授权和未登录结果返回
        http.exceptionHandling()
                //访问拒绝处理(权限不足)
                .accessDeniedHandler(resstfulAccessDeniedHandler)
                //重新认证入口点(未登录)
                .authenticationEntryPoint(restAuthorizationEntryPoint);
    }

    @Override
    @Bean
    public UserDetailsService userDetailsService(){
            return username->{
            Admin admin = adminService.getAdminByUserName(username);
            if (null!=admin){
                return admin;
            }
            return null;
        };
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public JwtAuthencationTokenFilter jwtAuthencationTokenFilter(){
        return new JwtAuthencationTokenFilter();
    }
}

7RestAuthorizationEntryPoint

package com.xxxx.server.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxxx.server.pojo.RespBean;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 未登录时返回的结果
 */
@Component
public class RestAuthorizationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        PrintWriter out =httpServletResponse.getWriter();
        RespBean bean = RespBean.error("未登录");
        bean.setCode(401);
        out.write(new ObjectMapper().writeValueAsString(bean));
        out.flush();
        out.close();
    }
}

8RestfulAccessDeniedHandle

package com.xxxx.server.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxxx.server.pojo.RespBean;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 权限不足返回的结果
 */
@Component
public class ResstfulAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json");
        PrintWriter out = httpServletResponse.getWriter();
        RespBean bean=RespBean.error("权限不足");
        bean.setCode(403);
        out.write(new ObjectMapper().writeValueAsString(bean));
        out.flush();
        out.close();
    }
}

9ScurityConfig(增加Swagger2配置)

package com.xxxx.server.config.security;

import com.xxxx.server.pojo.Admin;
import com.xxxx.server.service.IAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private IAdminService adminService;
    @Autowired
    private RestAuthorizationEntryPoint restAuthorizationEntryPoint;
    @Autowired
    private ResstfulAccessDeniedHandler resstfulAccessDeniedHandler;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }
    //允许基于选择匹配在资源级配置基于网络的安全性
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                //基于token,不要session
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)/*
                    ALWAYS
                    总是创建HttpSession  IF_REQUIRED
                    Spring Security只会在需要时创建一个HttpSession
                    NEVER
                    Spring Security不会创建HttpSession,但如果它已经存在,将可以使用HttpSession
                    STATELESS
                    Spring Security永远不会创建HttpSession,它不会使用HttpSession来获取SecurityContext

 */
                .and()
                .authorizeRequests()
                //websecurity已经配置
                .antMatchers("/login","/logout")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .headers()
                .cacheControl();
                //添加登录授权拦截器
        http.addFilterBefore(jwtAuthencationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
                //自定义未授权和未登录结果返回
        http.exceptionHandling()
                //访问拒绝处理(权限不足)
                .accessDeniedHandler(resstfulAccessDeniedHandler)
                //重新认证入口点(未登录)
                .authenticationEntryPoint(restAuthorizationEntryPoint);
    }

    //用于影响全局安全性(配置资源,设置调试模式,通过实现自定义防火墙定义拒绝请求)的配置设置。
    //
    //一般用于配置全局的某些通用事物,例如静态资源等
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/login","/logout","/css/**",
                        "/js/**","/index.html","favicon.ico","/doc.html",
                        "/webjars/**","/swagger-resources/**","/v2/api-docs/**");
    }

    /**
     * 拉姆达表达式
     * @return
     */
    @Override
    @Bean
    public UserDetailsService userDetailsService(){

            return username->{
            Admin admin = adminService.getAdminByUserName(username);
            if (null!=admin){
                return admin;
            }
            return null;
        };
    }
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Bean
    public JwtAuthencationTokenFilter jwtAuthencationTokenFilter(){
        return new JwtAuthencationTokenFilter();
    }
}

10Swagger2Config

package com.xxxx.server.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableSwagger2
public class Swagger2Config {
    @Bean
    public Docket createRestApi(){
        //文档类型SWAGGER_2
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xxxx.server.controller"))
                .paths(PathSelectors.any())
                .build()
                .securityContexts(securityContexts())
                .securitySchemes(securitySchemes());
    }
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("云e办")
                .description("云e办接口文档")
                //内容
                .contact(new Contact("xxxx","http:8081/doc.html","xxxx@xxxx.com"))
                .version("1.0")
                .build();
    }

    private List<ApiKey> securitySchemes() {
        List<ApiKey> result = new ArrayList<>();
        ApiKey apiKey = new ApiKey("Authorization", "Authorization", "Header");
        result.add(apiKey);
        return result;
        }

     private List<SecurityContext> securityContexts(){
        //设置需要登录认证的的路径
         List<SecurityContext> result = new ArrayList<>();
         result.add(getContextByPath("/hello/.*"));
         return result;
     }

    private SecurityContext getContextByPath(String pathRegex) {
       return springfox.documentation.spi.service.contexts.SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(pathRegex))
                .build();
    }

    private List<SecurityReference> defaultAuth() {
        List<SecurityReference> result = new ArrayList<>();
        AuthorizationScope  authorizationScope=new AuthorizationScope("global","accessEverything");
        AuthorizationScope[] authorizationScopes=new AuthorizationScope[1];
        authorizationScopes[0]=authorizationScope;
        //下面要求要数组才这样
        result.add(new SecurityReference("Authorization",authorizationScopes));
        return  result;

    }

}

云e办笔记(删减)的更多相关文章

  1. 【山外笔记-云原生】《Docker+Kubernetes应用开发与快速上云》读书笔记-2020.04.25(六)

    书名:Docker+Kubernetes应用开发与快速上云 作者:李文强 出版社:机械工业出版社 出版时间:2020-01 ISBN:9787111643012 [山外笔记-云原生]<Docke ...

  2. mysql部署到云主机的笔记

    写了个程序,需要把数据库部署到云主机上 MySQL基于安全考虑root账户一般只能本地访问,但是在开发过程中可能需要打开root的远程访问权限 为了安全,新添加一个用户来进行远程登录 登录MYSQL: ...

  3. 阿里云服务器部署笔记一(python3、Flask、uWSGI、Nginx)

    一.重置密码,并重启服务器 二.安全组配置>配置规则>添加安全组规则(为了能在本地ssh到实例) 配置如下: 此配置为允许任意公网IP登陆实例,注意windows与Linux系统端口范围不 ...

  4. 《Docker容器与容器云》读书笔记

    云计算平台 云计算是一种资源的服务模式,该模式可以实现随时随地.便捷按需地从可配置计算资源共享池中获取所需资源(如网络.服务器.存储.应用及服务),资源能够快速供应并释放,大大减少了资源管理工作开销. ...

  5. 阿里云ubuntu环境笔记

    安装jdk8 1.下载JDK 从官网下载jdk8 jdk-8u5-linux-x64.tar.gz 2.解压 $ tar -zxvf jdk-8u5-linux-x64.tar.gz 解压出来是一个j ...

  6. 【云迁移论文笔记】A Comparison of On-premise to Cloud Migration Approaches

    A Comparison of On-premise to Cloud Migration Approaches Author Info: Claus Pahl senior lecturer at ...

  7. 【云迁移论文笔记】Cloud Migration Research:A Systematic Review

    Cloud Migration Research:A Systematic Review Author Info: Pooyan Jamshidi PhD Postdoctoral Researche ...

  8. 阿里云服务器部署笔记二(python3、Flask、uWSGI、Nginx)

    从git上把项目拉到服务器,项目可以在服务器上运行后,就只需要配置uwsgi和nginx了.它们的逻辑关系是:外部请求->nginx->uwsgi->项目实例. 一.配置uwsgi ...

  9. 阿里云serverless使用笔记

    1.使用api网关服务,创建完api后,测试时,需要传“请求签名”,否则会报401 ‘Empty Signature’错误.相关文档<错误编码表,请求签名>.(错误信息放置与响应头的‘x- ...

随机推荐

  1. ApacheCN 深度学习译文集 20201229 更新

    新增了七个教程: TensorFlow 和 Keras 应用开发入门 零.前言 一.神经网络和深度学习简介 二.模型架构 三.模型评估和优化 四.产品化 TensorFlow 图像深度学习实用指南 零 ...

  2. JavaCV的摄像头实战之五:推流

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<JavaCV的摄像头实战> ...

  3. 如何高效地写 Form

    工作少不了写"增删改查","增删改查"中的"增"和"改"都与 Form 有关,可以说:提升了 Form 的开发效率,就提 ...

  4. Linux-标准输入标准输出

    标准输入(代码为0) 标准输出(代码为1) 标准错误输出(代码为2) 将标准输出重定向到一个文件 find /etc -name fileA >list 等同于 find /etc -name ...

  5. Kubernetes二进制(单/多节点)部署

    Kubernetes二进制(单/多节点)部署 目录 Kubernetes二进制(单/多节点)部署 一.常见的K8S部署方式 1. Minikube 2. Kubeadmin 3. 二进制安装部署 4. ...

  6. jqGrid 修改单元格值或者替换图片及其他

     var rowIds = jQuery("#list1").jqGrid('getDataIDs');                for (var k = 0; k < ...

  7. 帆软报表(finereport)table块钻取,返回记住table块位置

    <1>首先table块加初始化事件,idex为参数,参数值为$tab_idexsetTimeout(function(){_g().getWidgetByName("tabpan ...

  8. 使用PHP利用phpmailer发送电子邮件

    先来几句废话:    phpMailer是一个非常强大的php发送邮件类,可以设定发送邮件地址.回复地址.邮件主题.html网页,上传附件,并且使用起来非常方便.     phpMailer的特点:  ...

  9. Spring Boot 自动配置(基本配置)

    在关于Spring Boot的第一篇中就提到了其几大特性,其中关于Java配置简化属性注入在上一篇SpringBoot外部配置 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中已经介绍. ...

  10. pytest--配置用例执行顺序(pytest_ordering插件介绍)

    前言 设置测试用例执行顺序: 默认情况下,pytest测试用例的执行顺序是按先外层后内层(目录下的文 件),再根据名称按ascii码值的顺序升序执行. 如果想自定义pytest测试用例的执行顺序,可以 ...