加入security+jwt安全策略
Pom中引入
        <!-- security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- jwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
加入后访问页面会弹出一个登录页,用户名为user,密码为启动时显示的一串字符串

但是这种页面及默认用户显然不是我们想要的,我们需要用户数据持久化,也需要合理分配权限。如下我们开始对security做基本的设置。
关于security+jwt主要有如下几个类设置
1.新建JwtUserDetails实现UserDetails
package com.tangruo.example.common.security;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
 * 安全用户模型
 * @author
 */
public class JwtUserDetails implements UserDetails {
    private static final long serialVersionUID = 1L;
    /**
     * 用户名:这是数据库的字段,
     * 是userName或者是account就写对应的字段
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    private String salt;
    /**
     *  权限集合
     */
    private Collection<? extends GrantedAuthority> authorities;
    JwtUserDetails(String username, String password, String salt, Collection<? extends GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.salt = salt;
        this.authorities = authorities;
    }
    /**无论我数据库里的字段是 `account`,或者username,或者userName,或者其他代表账户的字段,
     * 这里还是要写成 `getUsername()`,因为是继承的接口
     *
     * @return
     */
    @Override
    public String getUsername() {
        return username;
    }
    @JsonIgnore
    @Override
    public String getPassword() {
        return password;
    }
    public String getSalt() {
        return salt;
    }
    /**
     * 返回给用户的角色列表
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }
    /**
     * 账户是否未过期
     * @return
     */
    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /**
     *账户是否未锁定
     * @return
     */
    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    /**
     *密码是否未过期
     * @return
     */
    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /**
     *账户是否激活
     * @return
     */
    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return true;
    }
}
2.新建UserDetailsServiceImpl实现UserDetailsService
package com.rexyn.common.security;
import com.rexyn.system.entity.User;
import com.rexyn.system.service.AuthorityService;
import com.rexyn.system.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
 * 用户登录认证信息查询
 *
 * @author
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserService sysUserService;
    @Autowired
    private AuthorityService sysAuthorityService;
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        List<String>  Permissions;
        // 根据用户名查询用户是否存在
        User user = sysUserService.findUser(username,null);
        if (user == null) {
            // 用户不存在
            throw new UsernameNotFoundException(String.format("没有该用户 '%s'.", username));
        }else {
            // 用户存在,继续查询用户所拥有的所有权限
            Permissions = sysAuthorityService.findPermissionsByUsername(username);
        }
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        if (Permissions != null && Permissions.size() > 0) {
            // 遍历权限集合,将权限标识符添加到安全认证中心
            for (String  nameStr : Permissions) {
                SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(nameStr);
                grantedAuthorities.add(simpleGrantedAuthority);
            }
        }
        return new JwtUserDetails(username, user.getPassword(), user.getSalt(), grantedAuthorities);
    }
}
3.权限不足返回,新建AuthenticationAccessDeniedHandler实现AccessDeniedHandler类
package com.tangruo.example.common.security;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tangruo.example.common.api.ResultJson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
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;
/**
 * @author
 */
@Component
@Slf4j
public class AuthenticationAccessDeniedHandler implements AccessDeniedHandler {
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException) throws IOException, ServletException {
        // 登陆状态下,权限不足执行该方法
        // log.error("权限不足:" + accessDeniedException.getMessage());
        response.setStatus(HttpStatus.SC_OK);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter printWriter = response.getWriter();
        //printWriter.println(objectMapper.writeValueAsString(Result.fail(HttpStatus.SC_FORBIDDEN, accessDeniedException.getMessage())));
        printWriter.println(objectMapper.writeValueAsString(ResultJson.fail(HttpStatus.SC_FORBIDDEN+"", "权限不足,无法访问")));
        printWriter.flush();
        printWriter.close();
    }
}
4.登陆失效设置,新建JwtAuthenticationEntryPoint实现AuthenticationEntryPoint
package com.tangruo.example.common.security;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.httpclient.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tangruo.example.common.api.ResultJson;
import lombok.extern.slf4j.Slf4j;
@Component
@Slf4j
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
    @Autowired
    private ObjectMapper objectMapper;
    /**
     *
     */
    private static final long serialVersionUID = -4957913354424675827L;
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException, ServletException {
        // 验证为未登陆状态会进入此方法,认证错误
//      log.error("认证失败,请求接口:{},请求IP:{},请求参数:{},失败原因:{}", request.getRequestURI(), WebUtil.getIP(request),
//              JsonUtil.toJson(request.getParameterMap()), authException.getMessage());
        response.setStatus(HttpStatus.SC_OK);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        PrintWriter printWriter = response.getWriter();
        //printWriter.write(objectMapper.writeValueAsString(Result.fail(HttpStatus.SC_FORBIDDEN, authException.getMessage())));
        printWriter.write(objectMapper.writeValueAsString(ResultJson.fail(HttpStatus.SC_FORBIDDEN+"", "登录已失效,请重新登录")));
        printWriter.flush();
        printWriter.close();
    }
}
5.登陆验证规则重写,新建JwtAuthenticationProvider继承DaoAuthenticationProvider
package com.tangruo.example.common.security;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import com.tangruo.example.common.util.PasswordEncoder;
/**重写身份验证规则
 * @author tangruo
 *
 * 2021年1月4日
 */
public class JwtAuthenticationProvider extends DaoAuthenticationProvider{
    public JwtAuthenticationProvider(UserDetailsService userDetailsService) {
        setUserDetailsService(userDetailsService);
     }
     @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
            throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            logger.debug("Authentication failed: no credentials provided");
            throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
        String presentedPassword = authentication.getCredentials().toString();
        String salt = ((JwtUserDetails) userDetails).getSalt();
        // 覆写密码验证逻辑
        if (!new PasswordEncoder(salt).matches(userDetails.getPassword(), presentedPassword)) {
            logger.debug("Authentication failed: password does not match stored value");
            throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }
}
6.新建WebSecurityConfig继承WebSecurityConfigurerAdapter
package com.tangruo.example.common.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
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.core.userdetails.UserDetailsService;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import com.tangruo.example.common.security.AuthenticationAccessDeniedHandler;
import com.tangruo.example.common.security.JwtAuthenticationEntryPoint;
import com.tangruo.example.common.security.JwtAuthenticationProvider;
/**
 * 全局@author Sheldon
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * Spring会自动寻找实现接口的类注入,会找到我们的 UserDetailsServiceImpl  类
     */
    @Qualifier("userDetailsServiceImpl")
    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private AuthenticationAccessDeniedHandler authenticationAccessDeniedHandler;
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
    /**
     * anyRequest          |   匹配所有请求路径
     * access              |   SpringEl表达式结果为true时可以访问
     * anonymous           |   匿名可以访问
     * denyAll             |   用户不能访问
     * fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)
     * hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问
     * hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问
     * hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问
     * hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问
     * hasRole             |   如果有参数,参数表示角色,则其角色可以访问
     * permitAll           |   用户可以任意访问
     * rememberMe          |   允许通过remember-me登录的用户访问
     * authenticated       |   用户登录后可访问
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义身份验证组件
        auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 进行授权成功后处理。授权成功后,重定向回之前访问的页面(获取RequestCache中存储的地址)
        SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
        successHandler.setTargetUrlParameter("redirectTo");
        // 允许页面内嵌显示
        http.headers().frameOptions().disable();
        // 禁用 csrf, 由于使用的是JWT,我们这里不需要csrf
        http.cors().and().csrf().disable()
                // 认证失败处理类
                .exceptionHandling().accessDeniedHandler(authenticationAccessDeniedHandler)
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                .and()
                .authorizeRequests()
                // 跨域预检请求
                //.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                // 允许对于网站静态资源的无授权访问
                .antMatchers(HttpMethod.GET,
                        "/favicon.ico",
                        "/**/*.css",
                        "/**/*.js",
                        "/**/*.jpg",
                        "/**/*.png"
                ).permitAll()
                // 静态资源文件夹和swagger
                .antMatchers("/lib/**").permitAll()
                .antMatchers("/images/**").permitAll()
                .antMatchers("/temp/**").permitAll()
                .antMatchers("/doc.html").permitAll()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources").permitAll()
                .antMatchers("/v2/api-docs").permitAll()
                .antMatchers("/webjars/springfox-swagger-ui/**").permitAll()
                .antMatchers("/swagger/user/login").permitAll()
                // web jars
                .antMatchers("/webjars/**").permitAll()
                // 查看SQL监控(druid)
                .antMatchers("/druid/**").anonymous()
                .antMatchers("/home/**").permitAll()
                .antMatchers("/finance/**").permitAll()
                .antMatchers("/equipment/**").permitAll()
                .antMatchers("/equipment/findMainEquipments").permitAll()
                // 验证码
                .antMatchers("/oauth/captcha**").permitAll()
                .antMatchers("/layuiadmin/**").permitAll()
                //.antMatchers("").hasAnyAuthority("'',''")
                // 注册和登陆
                .antMatchers("/pages/system/login.jsp").permitAll()
                .antMatchers("/commons/*.jsp").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/user/*").permitAll()
                .antMatchers("/index").permitAll()
                //所有页面放开权限访问
                .antMatchers("/pages/**").permitAll()
                //配置生产管理接口访问权限登陆验证
                .antMatchers("/production/**").permitAll()
                //其他所有请求需要身份认证
                .anyRequest().authenticated()
                // 无权限的时候调用AuthenticationAccessDeniedHandler
                .and().exceptionHandling()
                .accessDeniedHandler(getAccessDeniedHandler())
        ;
        // 退出登录处理器
        http.logout().logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler());
        // token验证过滤器
        http.addFilterBefore(new BasicAuthenticationFilter(authenticationManager()),
                UsernamePasswordAuthenticationFilter.class);
         }
    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }
    @Bean
    public AccessDeniedHandler getAccessDeniedHandler() {
        return new AuthenticationAccessDeniedHandler();
    }
}
7.新建管理登陆接口类
包含自定义登录接口,登出接口,主页跳转功能
package com.tangruo.example.system.controller;
import com.alibaba.fastjson.JSONObject;
import com.tangruo.example.common.api.ResultJson;
import com.tangruo.example.common.security.CookieUtil;
import com.tangruo.example.common.security.JwtAuthenticatioToken;
import com.tangruo.example.common.security.JwtTokenUtils;
import com.tangruo.example.common.security.SecurityUtils;
import com.tangruo.example.common.util.DateUtils;
import com.tangruo.example.common.util.PasswordUtils;
import com.tangruo.example.common.util.StringUtil;
import com.tangruo.example.system.entity.AuthInfo;
import com.tangruo.example.system.entity.Resource;
import com.tangruo.example.system.entity.User;
import com.tangruo.example.system.service.ResourceService;
import com.tangruo.example.system.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
@Api(value = "用户登陆/退出管理", tags = "用户登陆/退出管理")
@Controller
public class UserLandingController {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private UserService sysUserService;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private ResourceService resourceService;
    @ApiOperation(value = "跳转主页,做动态菜单处理")
    @RequestMapping("/index")
    public String index( HttpServletRequest request,HttpServletResponse res) {
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        String username=authentication.getName();
        if (authentication.getName().equals("anonymousUser")||authentication.getPrincipal() instanceof String) {
            return "/system/login";
        }
        List<Resource> resources=resourceService.findByUsername(username);
        logger.info(JSONObject.toJSONString(resources));
        request.setAttribute("resource", resources);
        return "/index";
    }
    @ApiOperation(value = "主页识别")
    @RequestMapping("/")
    public void defaultIndex( HttpServletRequest request,HttpServletResponse res) throws IOException{
        Authentication authentication=SecurityContextHolder.getContext().getAuthentication();
        if (authentication.getName().equals("anonymousUser")||authentication.getPrincipal() instanceof String) {
            res.sendRedirect("/pages/system/login.jsp?");
            return;
        }
        res.sendRedirect("/index");
    }
    @ApiOperation(value = "用户登陆")
    @PostMapping("/user/login")
    public void sysUserLogin( HttpServletRequest request,HttpServletResponse res) throws IOException{
        logger.info("the login is running");
        String username=request.getParameter("username");
        String password=request.getParameter("password");
        if (StringUtil.isBlank(username)||StringUtil.isBlank(password)) {
            String msg="请输入用户名或密码";
            msg=URLEncoder.encode(msg,"UTF-8");
            res.sendRedirect("/pages/system/login.jsp?msg="+msg);
         return;
        }
        User sysUser = sysUserService.findUser(username,null);
        ResultJson<Object> resultJson = this.login(username , password,sysUser);
        if (resultJson != null) {
            String msg=resultJson.getMsg();
            msg=URLEncoder.encode(msg,"UTF-8");
            res.sendRedirect("/pages/system/login.jsp?msg="+msg);
            return;
        }
        // 系统登录认证
        AuthInfo authInfo = this.createAuthInfo(request, username , password);
        if (authInfo == null) {
            String msg="凭证错误";
            msg=URLEncoder.encode(msg,"UTF-8");
             res.sendRedirect("/pages/system/login.jsp?msg="+msg);
             return;
        }
        if (!StringUtil.isEmpty(sysUser.getLoginDate())) {
            authInfo.setLastUpdateTime(sysUser.getLoginDate());
        }
        sysUser.setLoginDate(DateUtils.getCurrDate());
        sysUserService.saveOrUpdate(sysUser);
        sysUser.setPassword(null);
        sysUser.setName(sysUser.getName()==null?sysUser.getUsername():sysUser.getName());
        HttpSession session = request.getSession();
        session.setAttribute("currentUser", sysUser);
        res.sendRedirect("/index");
    }
    // 校验账号和密码
    public  ResultJson<Object> login(String username, String password,User sysUser) {
        String salt;
        String objectPassword;
        Integer status;
        // 用户信息
        if (sysUser == null) {
            return ResultJson.fail("TX000001" , "账号不存在");
        }
        salt = sysUser.getSalt();
        objectPassword = sysUser.getPassword();
        status = sysUser.getEnable();
        // 账号不存在、密码错误
        if (!PasswordUtils.matches(salt, password, objectPassword)) {
            return ResultJson.fail("TX000002" , "密码不正确");
        }
        // 账号锁定
        if (status == 0) {
            return ResultJson.fail("TX000003" , "账号已被锁定,请联系管理员");
        }
        return null;
    }
    /**
     * 生成AuthInfo
     *
     */
    public AuthInfo createAuthInfo(HttpServletRequest request, String userName, String password) {
        try {
            JwtAuthenticatioToken token = SecurityUtils.login(request, userName, password, authenticationManager);
            logger.info("the token is: " + token);
            CookieUtil.writeCookie("token" , token.getToken());
            CookieUtil.writeCookie("uid" , userName);
            AuthInfo authInfo = new AuthInfo();
            authInfo.setTokenType(SecurityUtils.BEARER);
            authInfo.setUserName(userName);
            authInfo.setToken(token.getToken());
            authInfo.setExpiresIn(JwtTokenUtils.getExpire());
            return authInfo;
        } catch (Exception e) {
            logger.error("生成AuthInfo出错" , e);
            return null;
        }
    }
    @ApiOperation(value = "登出" , notes = "退出登录")
    @GetMapping(value = "/user/logout")
    public void logout(HttpServletRequest request,HttpServletResponse response) throws IOException {
        String token = StringUtil.isEmpty(request.getHeader("token")) ? CookieUtil.getCookie(request, "token") : request.getHeader("token");
         String msg = "退出登录成功";
         msg=URLEncoder.encode(msg,"UTF-8");
         if (token == null) {
            msg="退出登录失败";
             response.sendRedirect("/pages/system/login.jsp?msg="+msg);
             return;
         }
         CookieUtil.removeCookie("token");
         response.sendRedirect("/pages/system/login.jsp?msg="+msg);
    }
}
我用的登陆失效返回都是json数据,如果需要返回登录页,可以对4中进行设置。
有可能在上面的引用中会出现缺少类的问题。我这变引入了很多工具类,项目我重新打了一次压缩包(example-manage-2.0.zip)。可以进项目查看。
下载地址 网盘: https://pan.baidu.com/s/1c44hr0uCfRI_693JII6ylA 提取码: ghbk
返回目录springboot项目创建过程+maven+mybatis-plus+swagger+security
下一章:十.权限的使用
加入security+jwt安全策略的更多相关文章
- Spring Security + JWT实现前后端分离权限认证
		
现在国内前后端很多公司都在使用前后端分离的开发方式,虽然也有很多人并不赞同前后端分离,比如以下这篇博客就很有意思: https://www.aliyun.com/jiaocheng/650661.ht ...
 - Jhipster token签名异常——c.f.o.cac.security.jwt.TokenProvider     : Invalid JWT signature.
		
背景,jHipster自动生成的springBoot和angularJs前后台端分离的项目.java后台为了取到当前登录者的信息,所以后台开放了 MicroserviceSecurityConfigu ...
 - Spring Boot整合实战Spring Security JWT权限鉴权系统
		
目前流行的前后端分离让Java程序员可以更加专注的做好后台业务逻辑的功能实现,提供如返回Json格式的数据接口就可以.像以前做项目的安全认证基于 session 的登录拦截,属于后端全栈式的开发的模式 ...
 - 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目
		
一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...
 - Spring Security + JWT学习
		
开胃:Oauth2认证流程分析 现在第三方登录已经很普遍了,随便哪个App都会有使用微信登录,使用手机号码登录,或者使用支付宝登录等功能... 下面我们就以使用微信登录,做一个简单的流程分析分析 开胃 ...
 - Spring Boot Security JWT 整合实现前后端分离认证示例
		
前面两章节我们介绍了 Spring Boot Security 快速入门 和 Spring Boot JWT 快速入门,本章节使用 JWT 和 Spring Boot Security 构件一个前后端 ...
 - Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(二)
		
Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(二) 摘要 上一篇https://javaymw.com/post/59我们已经实现了基本的登录和t ...
 - Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一)
		
标题 Spring Boot+Spring Security+JWT 实现 RESTful Api 认证(一) 技术 Spring Boot 2.Spring Security 5.JWT 运行环境 ...
 - 4-12 Spring Security + JWT
		
Spring Security + JWT 此前,在处理登录的业务中,当视为登录成功时,返回的字符串并不是JWT数据,则应该将此数据改为必要的JWT数据. @Service public class ...
 - SpringBoot集成Security,JWT,Swagger全分析
		
GitHub地址: https://github.com/li-jun0201/springsecuritydemo本项目采用SpringBoot1.5.9, SpringSecurity,JWT, ...
 
随机推荐
- 解决 -Code 安装似乎损坏。请重新安装
			
问题: 1. 安装插件 fix VSCode Checksums 2. ctrl+shift+P打开命令面板 3. 输入 Fix Checksums: Apply 4. 重新启动VSCode
 - 在 openEuler 22.03 上安装 KubeSphere 实战教程
			
作者:老 Z,中电信数智科技有限公司山东分公司运维架构师,云原生爱好者,目前专注于云原生运维,云原生领域技术栈涉及 Kubernetes.KubeSphere.DevOps.OpenStack.Ans ...
 - 云原生周刊:Kubernetes v1.27 发布 | 2023.4.17
			
开源项目推荐 Palaemon Palaemon 是一个开源开发工具,用于监控 Kubernetes 集群的健康状况和资源指标并分析内存不足 (OOMKill) 错误. Gitkube Gitkube ...
 - 干活总结 | SQL 语法速成手册
			
本文针对关系型数据库的一般语法.限于篇幅,本文侧重说明用法,不会展开讲解特性.原理.本文内容包括基本概念.增删改查.子查询.连接和组合.函数.排序和分组.数据定义.事务处理.权限管理等等. 一.基本概 ...
 - Win11安装基于WSL2的Ubuntu
			
1. 概述 趁着还没有完全忘记,详细记录一下在Win11下安装基于WSL2的Ubuntu的详细过程.不得不说WLS2现在被微软开发的比较强大了,还是很值得安装和使用的,笔者就通过WLS2安装的Ubun ...
 - Python3 编程面试题
			
Python global 语句的作用 lambda 匿名函数好处 Python 错误处理 Python 内置错误类型 简述 any() 和 all() 方法 Python 中什么元素为假? 提高 P ...
 - SQL Server创建用户只能访问指定数据库和视图
			
我们在给数据库用户赋予权限时,有时候不想让该用户看到太多过程表和过程视图,这时就需要限定用户的访问权限 第一步:创建用户 创建数据库连接后,进入安全性--登录名,单击右键,新建登录名,并设置默认数据库 ...
 - composer 基础操作
			
一.composer入门 1.每次安装新的包文件,会更新/vendor/autoload.php文件 2.composer.lock与composer.json的关系 文件composer.lock会 ...
 - Paypal绑定招商银行 —— Paypal绑定收款银行账户的注意事项
			
地址: https://code.newban.cn/446.html
 - 5.3 Linux Vim三种工作模式
			
通过前面的学习我们知道,Linux 系统中所有的内容都以文件的形式进行存储,当在命令行下更改文件内容时,常会用到文本编辑器. 我们首选的文本编辑器是 Vim(至于为什么,可查看<Vi和Vim之间 ...