栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring security+jwt 实现认证授权

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring security+jwt 实现认证授权

目录结构

具体代码 config 配置类

DefaultControllerAdvice.java

package com.stu.manage.demo.config;

import com.stu.manage.demo.result.Result;
import com.stu.manage.demo.result.ResultEnum;
import com.stu.manage.demo.result.ResultUtil;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;




MybatisPlusConfig.java

package com.stu.manage.demo.config;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
// 配置类
// 如果这里使用 @MapperScan 则 在启动类 SpingbootTestApplication@MapperScan可以不用写
//@MapperScan("com.lomonkey.mapper")
@Configuration
@EnableTransactionManagement // 开启注解事务管理,等同于xml配置文件中的 
public class MybatisPlusConfig implements TransactionManagementConfigurer {
    @Resource(name="txManager1")
    private PlatformTransactionManager txManager1;
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        paginationInnerInterceptor.setOverflow(true);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(50L);
        // 开启 count 的 join 优化,只针对部分 left join
        //paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
//        paginationInnerInterceptor.setDialect();
        // 添加分页拦截器插件
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        // 添加乐观锁配置
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
    
    // 创建事务管理器1  其中DataSource会自动注入
    //在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
    // 关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager
    // 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。
    // 如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。
    @Bean(name = "txManager1")
    public PlatformTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    // 创建事务管理器2
    
    // 实现接口 TransactionManagementConfigurer 方法,其返回值代表在拥有多个事务管理器的情况下默认使用的事务管理器
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager1;
    }
}

MymetaObjectHandler

package com.stu.manage.demo.config;
import java.util.Date;
import org.apache.ibatis.reflection.metaObject;
import org.springframework.stereotype.Component;
import com.baomidou.mybatisplus.core.handlers.metaObjectHandler;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component //一定不要忘记吧处理器加到IOC容器中
public class MymetaObjectHandler implements metaObjectHandler {
    //插入时候的填充策略
    @Override
    public void insertFill(metaObject metaObject) {
        //设置字段的值(String fieldName字段名,Object fieldVal要传递的值,metaObject metaObject)
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.strictInsertFill(metaObject, "modifyTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
    }
    //更新时间的填充策略
    @Override
    public void updateFill(metaObject metaObject) {
        this.strictUpdateFill(metaObject, "modifyTime", Date.class, new Date()); // 起始版本 3.3.0(推荐使用)
    }
}

SecurityConfiguration.java

package com.stu.manage.demo.config;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlbasedCorsConfigurationSource;
import com.stu.manage.demo.config.service.UserDetailsServiceImpl;
import com.stu.manage.demo.constants.SecurityConstants;
import com.stu.manage.demo.exception.JwtAccessDeniedHandler;
import com.stu.manage.demo.exception.JwtAuthenticationEntryPoint;
import com.stu.manage.demo.filter.JWTAuthenticationFilter;
import com.stu.manage.demo.filter.JwtAuthorizationFilter;
import static java.util.Collections.singletonList;
import static org.springframework.security.config.Customizer.withDefaults;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    private final StringRedisTemplate stringRedisTemplate;
    @Autowired
    private JwtAccessDeniedHandler jwtAccessDeniedHandler;
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    public SecurityConfiguration(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }
    
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
    @Bean
    @Override
    protected UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 设置自定义的userDetailsService以及密码编码器
        auth.userDetailsService(userDetailsService()).passwordEncoder(bCryptPasswordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors(withDefaults())
                .csrf().disable() // 禁用 CSRF 禁用自带的跨域策略
                .authorizeRequests()
                // 指定的接口直接放行
                .antMatchers(SecurityConstants.SWAGGER_WHITELIST).permitAll() // swagger
                //.antMatchers(HttpMethod.GET, SecurityConstants.SYSTEM).permitAll()
                .antMatchers(HttpMethod.POST, SecurityConstants.AUTH_LOGIN_URL).permitAll()
                //.antMatchers(SecurityConstants.HAS_AUTH).hasAuthority("SystemUserUpdate")
                //.antMatchers("student/insert
    }
    
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(singletonList("*"));
        // configuration.setAllowedOriginPatterns(singletonList("*"));
        configuration.setAllowedHeaders(singletonList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "DELETE", "PUT", "OPTIONS"));
        configuration.setExposedHeaders(singletonList(SecurityConstants.TOKEN_HEADER));
        configuration.setAllowCredentials(false);
        configuration.setMaxAge(3600L);
        UrlbasedCorsConfigurationSource source = new UrlbasedCorsConfigurationSource();
        source.registerCorsConfiguration("
    public static final String ROLE_CLAIMS = "rol";

    
    public static final long EXPIRATION = 60 * 60L;

    
    public static final long EXPIRATION_REMEMBER = 60 * 60 * 24 * 7L;

    
    public static final String JWT_SECRET_KEY = "C*F-JaNdRgUkXn2r5u8x/A?D(G+KbPeShVmYq3s6v9y$B&E)H@McQfTjWnZr4u7w";
    // JWT token defaults
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String TOKEN_TYPE = "JWT";
    // Swagger WHITELIST
    public static final String[] SWAGGER_WHITELIST = {
            "/swagger-ui.html",
            "/swagger-ui
    @PostMapping("/login-up")
    public Result login(@RequestBody LoginRequest loginRequest) {
        String token = null;
        try {
            token = loginService.createToken(loginRequest);
        } catch (Exception e) {
            log.error(e.getMessage());
            return ResultUtil.error(ResultEnum.VERIFY_FAIL.getCode(), ResultEnum.VERIFY_FAIL.getMsg());
        }
        LoginToken loginToken = new LoginToken();
        loginToken.setName(loginRequest.getUsername());
        loginToken.setToken(token);
        
        return ResultUtil.success(loginToken);
       // return new ResponseEntity<>(httpHeaders, HttpStatus.OK);
    }
}
StudentController
package com.stu.manage.demo.controller;
import com.stu.manage.demo.result.Result;
import com.stu.manage.demo.result.ResultEnum;
import com.stu.manage.demo.result.ResultUtil;
import com.stu.manage.demo.service.StudentService;
import com.stu.manage.demo.entity.Student;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/student")
@Slf4j
public class StudentController {
    @Autowired
    private StudentService studentService;
    @GetMapping("/getAll")
//    @PreAuthorize("hasAnyRole('ROLE_ADMIN')")
    @PreAuthorize("hasAuthority('SystemContent')")
    public Result getAllStudents(){
        List res = studentService.getAllStudents();
        if(res!=null) {
            return ResultUtil.success(res);
        }else {
            return ResultUtil.error(ResultEnum.DATA_IS_NULL.getCode(),ResultEnum.DATA_IS_NULL.getMsg());
        }
    }
    @GetMapping("/find/id/{id}")
    public Result studentById(@PathVariable("id")Integer id){
        List res=studentService.getStudentById(id);
        if(!res.isEmpty()){
            return ResultUtil.success(res);
        }else {
            return ResultUtil.error(ResultEnum.STUDENT_NOT_EXIST.getCode(),ResultEnum.STUDENT_NOT_EXIST.getMsg());
        }

    }
    @PostMapping ("/insert")
    public Result insert(@RequestBody @Valid Student student){
        int res=studentService.insertStudent(student);
        if(res==1){
            return ResultUtil.success(res);
        }else {
            return ResultUtil.error(ResultEnum.UNKNOWN_ERROR.getCode(),ResultEnum.UNKNOWN_ERROR.getMsg());
        }
    }
    @PostMapping("/update")
    //@PreAuthorize("hasAnyRole('ROLE_ROOT')")
    @PreAuthorize("hasAuthority('SystemUserUpdate')")
    public Result update(@RequestBody @Valid Student student){
         int res=studentService.updateStudent(student);
         if(res>0){
             return ResultUtil.success();
         }else {
             return ResultUtil.error(ResultEnum.UPDATE_FAIL.getCode(),ResultEnum.UPDATE_FAIL.getMsg());
         }
    }
}

LoginRequest

package com.stu.manage.demo.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class LoginRequest {
    private String username;
    private String password;
    private Boolean rememberMe;
}
entity 

 JwtUser

package com.stu.manage.demo.entity;
import java.util.Collection;
import java.util.List;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class JwtUser implements UserDetails {
    private Long id;
    private String username;
    private String password;
    private Boolean enabled;
    private Collection authorities;
    public JwtUser(TbUser tbUser) {
        this.id = tbUser.getId();
        this.username = tbUser.getUserName();
        this.password = tbUser.getPassWord();
        this.enabled = tbUser.getEnabled() == null ? true : tbUser.getEnabled();;
    }
    public void setAuthorities(List list) {
        this.authorities = list;
    }
    public JwtUser() {}
    @Override
    public Collection getAuthorities() {
        return authorities;
    }
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }
    public Long getId() {
        return id;
    }
}

 LoginToken

package com.stu.manage.demo.entity;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Data
@ToString
public class LoginToken {
    @NotNull
    private String name;
    private String token;
}

Student 

 
package com.stu.manage.demo.entity;
import java.util.Date;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Builder;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@Builder
public class Student {
    
    @TableId(value = "student_id", type = IdType.AUTO)
    private Integer studentId;
    @TableField("student_name")
    @NotBlank(message = "姓名不能为空")
    private String studentName;
    @TableField("id_card")
    @NotBlank(message = "身份证不能为空")
    private String idCard;
    @NotNull
    private String sex;
    @TableField("grade_id")
    @NotNull
    private Integer gradeId;
    @TableField("class_id")
    @NotNull
    private Integer classId;
    @TableField(value = "createtime", fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(value = "modifytime", fill = FieldFill.INSERT_UPDATE)
    private Date modifyTime;
    
    @Version //乐观锁Version注解
    private Integer version;
}
TbAuditbase
package com.stu.manage.demo.entity;
import java.util.Date;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
public class TbAuditbase {
    @TableField(value = "created", fill = FieldFill.INSERT)
    @NotNull
    private Date createTime;
    @TableField(value = "updated", fill = FieldFill.UPDATE)
    @NotNull
    private Date modifyTime;
}

TbPermission

package com.stu.manage.demo.entity;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class TbPermission extends TbAuditbase {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableField("parent_id")
    @NotNull
    private Long parentId;
    @NotNull
    private String name;
    @NotNull
    private String enname;
    @NotNull
    private String url;
    private String description;
}

TbRole

package com.stu.manage.demo.entity;
import java.util.List;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@TableName(value = "tb_role", resultMap = "baseResultMap")
@AllArgsConstructor
@NoArgsConstructor
public class TbRole extends TbAuditbase {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableField("parent_id")
    @NotNull
    private Long parentId;
    @NotNull
    private String name;
    @NotNull
    private String enname;
    private String description;
    // 一对多
    private List rolePermissions;
}
TbRolePermission
package com.stu.manage.demo.entity;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class TbRolePermission {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableField("permission_id")
    @NotNull
    private Long permissionId;
    @TableField("role_id")
    @NotNull
    private Long roleId;
}

 TbUser

package com.stu.manage.demo.entity;
import java.util.List;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Builder
@TableName(value = "tb_user", resultMap = "baseResultMap")
@AllArgsConstructor
@NoArgsConstructor
public class TbUser extends TbAuditbase {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableField("username")
    @NotNull
    private String userName;
    @TableField("password")
    @NotNull
    private String passWord;
    @NotNull
    private String phone;
    private String email;
    private Boolean enabled;
    
    private List userRoles;
}
TbUserRole
package com.stu.manage.demo.entity;
import javax.validation.constraints.NotNull;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Builder;
import lombok.Data;
@Data
@Builder
public class TbUserRole {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableField("user_id")
    @NotNull
    private Long userId;
    @TableField("role_id")
    @NotNull
    private Long roleId;
}
exception 

 JwtAccessDeniedHandler

package com.stu.manage.demo.exception;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

@Component
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
    
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
        accessDeniedException = new AccessDeniedException("无权限操作!!");
        response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
        
    }
}

JwtAuthenticationEntryPoint

package com.stu.manage.demo.exception;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
    
    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response,
                         AuthenticationException authException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
    }
}
filter 

 JWTAuthenticationFilter

 

package com.stu.manage.demo.filter;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.stu.manage.demo.constants.SecurityConstants;
import com.stu.manage.demo.dto.LoginRequest;
import com.stu.manage.demo.entity.JwtUser;
import com.stu.manage.demo.utils.JwtTokenUtils;
// 认证过滤器
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private final StringRedisTemplate stringRedisTemplate;
    private ThreadLocal rememberMe = new ThreadLocal<>();
    private AuthenticationManager authenticationManager;
    public JWTAuthenticationFilter(AuthenticationManager authenticationManager, StringRedisTemplate stringRedisTemplate) {
        this.authenticationManager = authenticationManager;
        this.stringRedisTemplate = stringRedisTemplate;
        // 设置登录请求的 URL
        super.setFilterProcessesUrl(SecurityConstants.AUTH_LOGIN_URL);
    }
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response) throws AuthenticationException {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            // 从输入流中获取到登录的信息
            LoginRequest loginRequest = objectMapper.readValue(request.getInputStream(), LoginRequest.class);
            rememberMe.set(loginRequest.getRememberMe());
            // 这部分和attemptAuthentication方法中的源码是一样的,
            // 只不过由于这个方法源码的是把用户名和密码这些参数的名字是死的,所以我们重写了一下
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                    loginRequest.getUsername(), loginRequest.getPassword());
            return authenticationManager.authenticate(authRequest);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    
    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                                            HttpServletResponse response,
                                            FilterChain chain,
                                            Authentication authentication) {
        JwtUser jwtUser = (JwtUser) authentication.getPrincipal();
        List roles = jwtUser.getAuthorities()
                .stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());
        // 创建 Token
        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), jwtUser.getId().toString(), roles, rememberMe.get());
        stringRedisTemplate.opsForValue().set(jwtUser.getId().toString(), token);
        // Http Response Header 中返回 Token
        response.setHeader(SecurityConstants.TOKEN_HEADER, token);
    }
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
    }
}

JwtAuthorizationFilter 

 

package com.stu.manage.demo.filter;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.stu.manage.demo.constants.SecurityConstants;
import com.stu.manage.demo.utils.JwtTokenUtils;
import io.jsonwebtoken.JwtException;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
    private final StringRedisTemplate stringRedisTemplate;
    public JwtAuthorizationFilter(AuthenticationManager authenticationManager, StringRedisTemplate stringRedisTemplate) {
        super(authenticationManager);
        this.stringRedisTemplate = stringRedisTemplate;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        String token = request.getHeader(SecurityConstants.TOKEN_HEADER);
        if (token == null || !token.startsWith(SecurityConstants.TOKEN_PREFIX)) {
            SecurityContextHolder.clearContext();
            chain.doFilter(request, response);
            return;
        }
        String tokenValue = token.replace(SecurityConstants.TOKEN_PREFIX, "");
        UsernamePasswordAuthenticationToken authentication = null;
        try {
            String previousToken = stringRedisTemplate.opsForValue().get(JwtTokenUtils.getId(tokenValue));
            if (!token.equals(previousToken)) {
                SecurityContextHolder.clearContext();
                chain.doFilter(request, response);
                return;
            }
            authentication = JwtTokenUtils.getAuthentication(tokenValue);
        } catch (JwtException e) {
            logger.error("Invalid jwt : " + e.getMessage());
        }
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);
    }
}
mapper 

 TbPermissionMapper

package com.stu.manage.demo.mapper;
import java.util.List;
import org.springframework.stereotype.Repository;
import com.baomidou.mybatisplus.core.mapper.baseMapper;
import com.stu.manage.demo.entity.TbPermission;
import com.stu.manage.demo.entity.TbUser;
@Repository
public interface TbPermissionMapper extends baseMapper {
    List findByUser(TbUser tbUser);
}

TbPermissionMapper.xml 




  
    
    
    
    
    
    
    
    
  
  
    id, parent_id, `name`, enname, url, description, created, updated
  
  
        select id, user_id, role_id from tb_user_role where user_id = #{id}
  
  
    id, username, `password`, phone, email, created, updated
  
 result

Result

package com.stu.manage.demo.result;
import lombok.Data;
@Data
public class Result {
    private Integer code;
    private String msg;
    private T data;
    public Result() {
        super();
    }
    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", msg='" + msg + ''' +
                ", data=" + data +
                '}';
    }
}

ResultEnum 

package com.stu.manage.demo.result;
public enum ResultEnum {
    //可自行定义,与前端交互
    UNKNOWN_ERROR(-1,"未知错误"),
    SUCCESS(200,"成功"),
    STUDENT_NOT_EXIST(1,"学生不存在"),
    STUDENT_IS_EXISTS(2,"学生已存在"),
    DATA_IS_NULL(3,"数据为空"),
    DELETE_FAIL(5,"删除失败"),
    UPDATE_FAIL(6,"更新失败"),
    VERIFY_FAIL(7,"验证失败")
    ;
    private Integer code;
    private String msg;
    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public Integer getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

ResultUtil

package com.stu.manage.demo.result;
public class ResultUtil {
    
    public static Result success(Object object){
        Result result = new Result();
        result.setCode(ResultEnum.SUCCESS.getCode());
        result.setMsg(ResultEnum.SUCCESS.getMsg());
        result.setData(object);
        return result;
    }
    
    public static Result success(){
        return success(null);
    }
    
    public static Result error(Integer code,String msg){
        Result result = new Result();
        result.setCode(code);
        result.setMsg(msg);
        return result;
    }
}
service 

 LoginServiceImpl

package com.stu.manage.demo.service.impl;
import java.util.List;
import java.util.stream.Collectors;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.stu.manage.demo.dto.LoginRequest;
import com.stu.manage.demo.entity.TbPermission;
import com.stu.manage.demo.entity.TbUser;
import com.stu.manage.demo.mapper.LoginMapper;
import com.stu.manage.demo.mapper.TbUserMapper;
import com.stu.manage.demo.service.ITbPermissionService;
import com.stu.manage.demo.service.ITbUserService;
import com.stu.manage.demo.service.LoginService;
import com.stu.manage.demo.utils.JwtTokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class LoginServiceImpl implements LoginService {
    private static final String TAG = LoginServiceImpl.class.getName();
//    private static final Logger logger = Logger.getLogger(LoginServiceImpl.class.getName());
    @Autowired
    private LoginMapper loginMapper;
    @Autowired
    private ITbUserService tbUserService;
    @Autowired
    private ITbPermissionService permissionService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Override
    public String getAdmin(String name){
        return loginMapper.getAdmin(name);
    }
    @Override
    public String createToken(LoginRequest loginRequest) {
        TbUserMapper mapper = tbUserService.getMapper();
        QueryWrapper queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userName", loginRequest.getUsername());
        TbUser tbUser = mapper.selectOne(queryWrapper);
        if (!tbUserService.check(loginRequest.getPassword(), tbUser.getPassWord())) {
            throw new BadCredentialsException("The username or password is not correct");
        }
        List permissions = permissionService.findByUser(tbUser).stream().map(TbPermission::getEnname).collect(Collectors.toList());
        String token = JwtTokenUtils.createToken(tbUser.getUserName(), tbUser.getId().toString(), permissions, true);
        log.info(TAG, "{} createToken is [}", tbUser.getUserName(), token);
        //logger.info("{} createToken is [}", tbUser.getUserName(), token);
        stringRedisTemplate.opsForValue().set(tbUser.getId().toString(), token);
        return token;
    }
}
utils 

CurrentUserUtils

package com.stu.manage.demo.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import com.stu.manage.demo.entity.TbUser;
import com.stu.manage.demo.service.ITbUserService;
import lombok.RequiredArgsConstructor;

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class CurrentUserUtils {
    private final ITbUserService tbUserService;
    public TbUser getCurrentUser() {
        return tbUserService.findByName(getCurrentUserName());
    }
    private String getCurrentUserName() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null && authentication.getPrincipal() != null) {
            return (String) authentication.getPrincipal();
        }
        return null;
    }
}

JwtTokenUtils 

package com.stu.manage.demo.utils;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.crypto.SecretKey;
import javax.xml.bind.DatatypeConverter;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import com.stu.manage.demo.constants.SecurityConstants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

public class JwtTokenUtils {
    
    private static final byte[] API_KEY_SECRET_BYTES = DatatypeConverter.parsebase64Binary(SecurityConstants.JWT_SECRET_KEY);
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(API_KEY_SECRET_BYTES);
    public static String createToken(String username, String id, List permissions, boolean isRememberMe) {
        long expiration = isRememberMe ? SecurityConstants.EXPIRATION_REMEMBER : SecurityConstants.EXPIRATION;
        final Date createdDate = new Date();
        final Date expirationDate = new Date(createdDate.getTime() + expiration * 1000);
        String tokenPrefix = Jwts.builder()
                .setHeaderParam("type", SecurityConstants.TOKEN_TYPE)
                .signWith(SECRET_KEY, SignatureAlgorithm.HS256) // 密钥
                .claim(SecurityConstants.ROLE_CLAIMS, String.join(",", permissions)) // 载荷
                .setId(id) // jwt唯一标识
                .setIssuer("SnailClimb") //jwt的签发者
                .setIssuedAt(createdDate) //jwt的签发标识
                .setSubject(username) //sub(Subject):代表这个JWT的主体,是一个json格式的字符串,作为什么用户的唯一标志
                .setExpiration(expirationDate) // 过期时间
                .compact(); //压缩为xxxxxxxxxxxxxx.xxxxxxxxxxxxxxx.xxxxxxxxxxxxx这样的jwt
        return SecurityConstants.TOKEN_PREFIX + tokenPrefix; // 添加 token 前缀 "Bearer ";
    }
    public static String getId(String token) {
        Claims claims = getClaims(token);
        return claims.getId();
    }
    public static UsernamePasswordAuthenticationToken getAuthentication(String token) {
        Claims claims = getClaims(token);
        List authorities = getAuthorities(claims);
        String userName = claims.getSubject();
        return new UsernamePasswordAuthenticationToken(userName, token, authorities);
    }
    private static List getAuthorities(Claims claims) {
        String role = (String) claims.get(SecurityConstants.ROLE_CLAIMS);
        return Arrays.stream(role.split(","))
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());
    }
    private static Claims getClaims(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody();
    }
}
validator 

FullName

package com.stu.manage.demo.validator;
import java.lang.annotation.documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;

@documented
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = FulleNamevalidator.class)
public @interface FullName {
    String message() default "姓名格式错误";
    Class[] groups() default {};
    Class[] payload() default {};
}

FulleNamevalidator

package com.stu.manage.demo.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FulleNamevalidator implements ConstraintValidator {
    
    private static final String FULL_NAME_REG_EXP = "(?!.*\s$)((?=\S)(?![0-9]+$)[\u4E00-\u9FA5A-Za-z0-9. ' ]{2,15})";
    @Override
    public boolean isValid(String fullNameStr, ConstraintValidatorContext context) {
        if (fullNameStr == null) {
            return true;
        }
        log.info("fullName is {}", fullNameStr);
        return fullNameStr.matches(FULL_NAME_REG_EXP);
    }
}

application.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useSSL=false&useUnicode=true&characterEncoding=utf-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
#spring.datasource.initialSize=20
#spring.datasource.minIdle=50
#spring.datasource.maxActive=500
server.port=8888
#mybatis plus
mybatis-plus.mapper-locations=classpath:mapper/*.xml
mybatis-plus.type-aliases-package=com.stu.manage.demo.entity
logging.level.com.stu.manage.demo.mapper = debug
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.timeout=10000
spring.redis.database=0
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-wait=-1
spring.redis.jedis.pool.max-idle=8
spring.redis.jedis.pool.min-idle=0
pom.xml 


    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.4.0
        
    
    com.stu-mange
    demo
    0.0.1-SNAPSHOT
    demo
    Demo project for Spring Boot
    
        1.8
        0.10.7
        29.0-jre
        4.13.1
    
    
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-validation
        
        
            org.springframework.boot
            spring-boot-starter-security
        
        
            org.springframework.security
            spring-security-test
            test
        
        
            org.springframework.boot
            spring-boot-starter-jdbc
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-web-services
        
        
            org.springframework.boot
            spring-boot-starter-webflux
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
        
            org.postgresql
            postgresql
            runtime
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            mysql
            mysql-connector-java
            runtime
        
        
            io.projectreactor
            reactor-test
            test
        
        
        com.microsoft.sqlserver
        mssql-jdbc
        runtime
        
        
        
            org.apache.httpcomponents
            httpclient
            4.5
        
        
            org.apache.httpcomponents
            httpmime
            4.5
        
        
            org.apache.httpcomponents
            httpcore
            4.4.1
        
        
            com.alibaba
            fastjson
            1.2.17
        
        
        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.4.0
        
        
        
            com.alibaba
            druid
            1.1.9
        
        
        
            io.springfox
            springfox-swagger2
            2.9.2
        
        
            io.springfox
            springfox-swagger-ui
            2.9.2
        
        
        
            org.projectlombok
            lombok
            true
        
        
        
            org.springframework.boot
            spring-boot-starter-data-redis
        
        
        
            io.jsonwebtoken
            jjwt-api
            ${jwt.version}
        
        
            io.jsonwebtoken
            jjwt-impl
            ${jwt.version}
            runtime
        
        
            io.jsonwebtoken
            jjwt-jackson
            ${jwt.version}
            runtime
        
        
        
            com.google.guava
            guava
            ${guava.version}
        
        
        
            junit
            junit
            ${junit.version}
            test
        
    
    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

 


该记录引用项目:https://github.com/Snailclimb/spring-security-jwt-guide、http://t.zoukankan.com/snailclimb-p-11631890.html

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/759623.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号