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. Java 书写规范简单整理

    本文带有华为Logo的PPT图片,引自:华为云课堂 目录 Java基础语句使用规范 选择结构 switch 默认要有default分支 注意break的使用 如果使用枚举,并且选项已全部列出,可以没有 ...

  2. 入门 - 复习Kubernetes核心概念 (八)

    本文将会简单介绍Kubernetes的核心概念.因为这些定义可以在Kubernetes的文档中找到,所以文章也会避免用大段的枯燥的文字介绍.相反,我们会使用一些图表(其中一些是动画)和示例来解释这些概 ...

  3. SSH 密钥登录

    一.什么是SSH? 简单说,SSH是一种网络协议,用于计算机之间的加密登录. 如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会 ...

  4. keystore文件

    [-] keystore操作 运行时签名文件路径debug 生成签名文件打包时使用 获取MD5和SH1 修改keystore文件密码 修改keystore文件别名 修改keystore文件别名的密码 ...

  5. linux安装python3.6.6和新建虚拟环境

    基础准备 修改本地时区 cp -rf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 安装epel yum源 yum -y install epel- ...

  6. Python--操作列表

    Python--操作列表 目录 Python--操作列表 一.遍历整个列表 1. 深入研究循环 2. 在for循环中执行更多操作 3. 在for循环结束后执行一些操作 二.避免缩进错误 1. 忘记缩进 ...

  7. notepad++颜色属性解释

    Global Styles Indent guideline style  缩进参考线的颜色Brace highlight style 鼠标指针在框架左右时框架的颜色(如css中{}   js中的() ...

  8. 员工管理系统+字符编码+Python代码文件操作

    员工管理系统+字符编码+Python代码文件操作 1.员工管理系统 1.1  debug 代码调试 1.先使用鼠标左键在需要调试的代码左边点击一下(会出现一个红点)2.之后右键点击debug运行代码 ...

  9. 2、Golang基础--包的使用、if-else语句、循环、switch语句、数组、切片、可变函数参数、map类型

    1 包的使用 // 为了便于组织代码,同一种类型的代码,写在同一个包下,便于管理 // 定义包 -新建一个文件夹 -内部有很多go文件 -在每个go文件的第一行,都要声明包名,并且包名必须一致 -在一 ...

  10. C++的Copy Elision导致的奇怪问题

    最近写设计模式作业的时候, 有一个作业是实现装饰器模式 (Decorator Pattern), 由于我不会 Java, 所以只能用 C++ 来实现 在这个背景下, 会有简单(表意)的几个类, 如下: ...