欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Security前后分離校驗(yàn)token的實(shí)現(xiàn)方法

 更新時(shí)間:2022年02月25日 09:17:17   作者:專注寫bug  
這篇文章主要介紹了Spring?Security前后分離校驗(yàn)token的方法,本次token生成采取jwt的方式,通過引入jwt依賴文件配置token管理器,對Spring?Security校驗(yàn)token相關(guān)知識(shí)感興趣的朋友一起看看吧

前言

之前采取項(xiàng)目中嵌套html頁面,實(shí)現(xiàn)基本的登錄校驗(yàn)、權(quán)限校驗(yàn)、登出操作記住我等功能試下。

但是,現(xiàn)在的開發(fā)基本都是前后分離樣式,后端并不需要配置登錄頁的操作。

如何才能做到前后分離,同時(shí)也能支持登錄token校驗(yàn)?zāi)?,本篇博客詳?xì)說明。

token配置

本次token生成采取jwt的方式。

引入JWT依賴文件

<dependency>
  <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.10.3</version>
</dependency>

配置token管理器類

自定一個(gè)Token生成和從token中解析用戶名的一個(gè)類,并交給Spring管理。

package security.config;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.stereotype.Component;
import java.util.Calendar;
import java.util.HashMap;
@Component
public class TokenJwtManager {
    // 設(shè)置token時(shí)間
    private int tokenEcpiration = 24*60*60*1000; // 毫秒   24h
    // 編碼密鑰
    private String tokenSignKey = "123456";
    // 1、根據(jù)用戶名生成token
    public String createToken(String userName){
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.SECOND, tokenEcpiration);
        String userName1 = JWT.create()
                .withHeader(new HashMap<>())
                .withClaim("userName", userName)
                .withExpiresAt(calendar.getTime()) // 過期時(shí)間
                .sign(Algorithm.HMAC256(tokenSignKey));// 簽名
        return userName1;
    }
    // 2、根據(jù)token得到用戶名信息
    public String getUserName(String token){
        JWTVerifier build = JWT.require(Algorithm.HMAC256(tokenSignKey)).build();
        DecodedJWT verify = build.verify(token);
        Claim userName = verify.getClaim("userName");
        return userName.asString();
    public static void main(String[] args) {
        String ss = new TokenJwtManager().createToken("1111111");
        System.out.println(ss);
        System.out.println(new TokenJwtManager().getUserName(ss));
}

security 配置

配置未登錄處理類

package security.config.handler;

import lombok.extern.slf4j.Slf4j;
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;
import java.util.HashMap;
import java.util.Map;
/**
 * 未登錄
 */
@Component
@Slf4j
public class MyUnAuthEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        log.info("======= commence ===");
        // 返回請求端
        Map<String,Object> resultMap = new HashMap<>();
        // 保存數(shù)據(jù)
        resultMap.put("code","10000");
        resultMap.put("msg","當(dāng)前賬戶未登錄");
        resultMap.put("data",new HashMap<>());
        // 設(shè)置返回消息類型
        httpServletResponse.setHeader("Content-type", "text/html;charset=UTF-8");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        // 返回給請求端
        PrintWriter writer  = httpServletResponse.getWriter();
        writer.write(resultMap.toString());
        writer.close();
    }
}

配置無權(quán)限處理類

package security.config.handler;

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;
import java.util.HashMap;
import java.util.Map;
/**
 * 無權(quán)訪問配置(前后分離)
 */
@Component  // 交給spring管理
public class MyAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        Map<String,Object> resultMap = new HashMap<>();
        // 保存數(shù)據(jù)
        resultMap.put("code","403");
        resultMap.put("msg","無權(quán)訪問");
        resultMap.put("data",null);
        // 設(shè)置返回消息類型
        httpServletResponse.setHeader("Content-type", "text/html;charset=UTF-8");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        // 返回給請求端
        PrintWriter writer = httpServletResponse.getWriter();
        writer.write(resultMap.toString());
        writer.flush();
        writer.close();
    }
}

配置登出操作處理類

package security.config.handler;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.stereotype.Component;
import security.config.TokenJwtManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
 * 登出
 */
@Component
@Slf4j
public class MyLogoutHandler implements LogoutHandler {
    @Autowired
    private TokenJwtManager tokenJwtManager;
//    public MyLogoutHandler(TokenJwtManager tokenJwtManager) {
//        this.tokenJwtManager = tokenJwtManager;
//    }
    @Override
    public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
        // 1、從header中獲取token
        String token = httpServletRequest.getHeader("token");
        log.info("token信息為  {}",token);
        String userName = tokenJwtManager.getUserName(token);
        log.info("從token獲取userName信息為  {}",token);
        // redis 移除登錄信息等邏輯
        // xxxxx
        // 2、返回請求端
        Map<String,Object> resultMap = new HashMap<>();
        // 保存數(shù)據(jù)
        resultMap.put("code","200");
        resultMap.put("msg",userName+"登錄成功");
        resultMap.put("data",new HashMap<>());
        // 設(shè)置返回消息類型
        httpServletResponse.setHeader("Content-type", "text/html;charset=UTF-8");
        httpServletResponse.setCharacterEncoding("utf-8");
        httpServletResponse.setContentType("application/json;charset=UTF-8");
        // 返回給請求端
        PrintWriter writer = null;
        try {
            writer = httpServletResponse.getWriter();
            writer.write(resultMap.toString());
            writer.flush();
            writer.close();
        } catch (IOException e) {
           e.printStackTrace();
        }
    }
}

配置token認(rèn)證過濾器

package security.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
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.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import security.config.TokenJwtManager;
import security.vo.SecurityUser;
import security.vo.User;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
// 這里交給spring管理會(huì)報(bào)錯(cuò)
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {
    private TokenJwtManager tokenJwtManager;
    private AuthenticationManager authenticationManager;
    public TokenLoginFilter(TokenJwtManager tokenJwtManager, AuthenticationManager authenticationManager) {
        this.tokenJwtManager = tokenJwtManager;
        this.authenticationManager = authenticationManager;
        this.setPostOnly(false); // 關(guān)閉登錄只允許 post
        // 設(shè)置登陸路徑,并且post請求
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/user/login","POST"));
    }
    // 1、獲取登錄頁傳遞來的賬戶和密碼信息
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        log.info("==== attemptAuthentication  ======");
        String userName = request.getParameter("userName");
        String pwd = request.getParameter("passWord");
        log.info("userName:{},pwd:{}",userName,pwd);
        return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(userName,
                pwd,new ArrayList<>()));
    // 2、認(rèn)證成功調(diào)用
    @Autowired
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        log.info("==== successfulAuthentication  ======");
        // 認(rèn)證成功之后,獲取認(rèn)證后的用戶基本信息
        SecurityUser securityUser = (SecurityUser) authResult.getPrincipal();
        // 根據(jù)用戶名生成對應(yīng)的token
        String token = tokenJwtManager.createToken(securityUser.getUsername());
        // token信息存于redis、數(shù)據(jù)庫、緩存等
        // 返回成功
        Map<String,Object> resultMap = new HashMap<>();
        // 保存數(shù)據(jù)
        resultMap.put("code","200");
        resultMap.put("msg","登錄成功");
        resultMap.put("data",token);
        // 設(shè)置返回消息類型
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=UTF-8");
        // 返回給請求端
        PrintWriter writer = response.getWriter();
        writer.write(resultMap.toString());
        writer.flush();
        writer.close();
    // 3、認(rèn)證失敗調(diào)用的方法
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed)
        log.info("==== unsuccessfulAuthentication  ======");
        resultMap.put("code","500");
        resultMap.put("msg","登錄驗(yàn)證失敗");
        resultMap.put("data",new HashMap<>());
}

配置token權(quán)限校驗(yàn)過濾器

package security.filter;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.stereotype.Component;
import security.config.TokenJwtManager;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
 * token 校驗(yàn)
 */
@Slf4j
//@Component // 交給 spring 會(huì)報(bào)錯(cuò)
public class TokenAuthFilter extends BasicAuthenticationFilter {
    private TokenJwtManager tokenJwtManager;
    public TokenAuthFilter(AuthenticationManager authenticationManager, TokenJwtManager tokenJwtManager) {
        super(authenticationManager);
        this.tokenJwtManager = tokenJwtManager;
    }
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("====  doFilterInternal   ==========   token校驗(yàn)");
        //獲取當(dāng)前認(rèn)證成功用戶權(quán)限信息
        UsernamePasswordAuthenticationToken authRequest = getAuthentication(request);
        if(authRequest != null){
            // 有權(quán)限,則放入權(quán)限上下文中
            SecurityContextHolder.getContext().setAuthentication(authRequest);
        }
        // 執(zhí)行下一個(gè) filter 過濾器鏈
        chain.doFilter(request,response);
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        log.info("==== getAuthentication =====");
        //從header獲取token
        String token = request.getHeader("token");
        log.info("token:{}",token);
        if(token != null) {
            //從token獲取用戶名
            String username = tokenJwtManager.getUserName(token);
            log.info("解析token獲取userName為:{}",username);
            // 數(shù)據(jù)庫獲取權(quán)限信息
            // 本次模擬
            List<String> permissionValueList = Arrays.asList("admin","select");
            Collection<GrantedAuthority> authority = new ArrayList<>();
            for(String permissionValue : permissionValueList) {
                SimpleGrantedAuthority auth = new SimpleGrantedAuthority(permissionValue);
                authority.add(auth);
            }
            return new UsernamePasswordAuthenticationToken(username,token,authority);
        return null;
}

自定義加密類

package security.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import security.utils.Md5Utils;
/**
 * 密碼加密、比對
 */
@Component // bean
@Slf4j
public class DefaultPwdEndoder implements PasswordEncoder {
    /**
     * 加密
     * @param charSequence
     * @return
     */
    @Override
    public String encode(CharSequence charSequence) {
        log.info("==== encode ====");
        log.info("charSequence 為 {}",charSequence);
        log.info("charSequence md5為 {}",Md5Utils.md5(charSequence.toString()));
        return Md5Utils.md5(charSequence.toString());
    }
     * 進(jìn)行密碼比對
     * @param charSequence 不加密
     * @param encodePwd  加密
    public boolean matches(CharSequence charSequence, String encodePwd) {
        log.info("==== matches ====");
        log.info("charSequence:{}",charSequence);
        log.info("charSequenceMd5:{}",Md5Utils.md5(charSequence.toString()));
        log.info("encodePwd:{}",encodePwd);
        return encodePwd.equalsIgnoreCase(Md5Utils.md5(charSequence.toString()));
}

配置UserDetailService

package security.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
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.Component;
import org.springframework.stereotype.Service;
import security.mapper.UserMapper;
import security.vo.SecurityUser;
import security.vo.User;
import java.util.Arrays;
import java.util.List;
/**
 * security 登錄信息和權(quán)限獲取類
 */
@Service("userDetailsService")
@Slf4j
public class UserDetailService implements UserDetailsService {
    // 注入U(xiǎn)sermapper
    @Autowired
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        log.info("====== loadUserByUsername ======");
        // 通過username查詢數(shù)據(jù)庫獲取用戶信息
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("username",userName);
        User user = userMapper.selectOne(userQueryWrapper);
        // 判斷用戶是否存在
        if(user == null){
            throw new UsernameNotFoundException("賬戶信息不存在!");
        }
        // 存在對應(yīng)的用戶信息,則將其封裝,丟給security自己去解析
        log.info("user:{}",user);
        // 權(quán)限暫時(shí)不查數(shù)據(jù)庫
        List<String> admin = Arrays.asList("ROLE_user,ROLE_admin,admin");
        // 將數(shù)據(jù)封裝給 SecurityUser ,因?yàn)?SecurityUser 是 UserDetails 的子類
        SecurityUser securityUser = new SecurityUser();
        securityUser.setPermissionValueList(admin);
        securityUser.setUser(user);
        log.info("securityUser:{}",securityUser.toString());
        return securityUser;
    }
}

配置數(shù)據(jù)庫User對象映射類

package security.vo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    private static final long serialVersionUID = -5461108964440966122L;
    private Integer id;
    private String username;
    private String password;
    private Integer enabled;
    private Integer locked;
}

配置UserDetailService使用的SecurityUser類

package security.vo;

import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
 * UserDetailService 使用該類,該類必須是 UserDetails 的子類
 */
@Data
public class SecurityUser implements UserDetails {
    // 登錄用戶的基本信息
    private User user;
    //當(dāng)前權(quán)限
    private List<String> permissionValueList;
    public SecurityUser() {
    }
    public SecurityUser(User user) {
        if (user != null) {
            this.user = user;
        }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        permissionValueList.forEach(permission ->{
            if(!StringUtils.isEmpty(permission)){
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permission);
                authorities.add(authority);
            }
        });
        return authorities;
    public String getPassword() {
        return user.getPassword();
    public String getUsername() {
        return user.getUsername();
    public boolean isAccountNonExpired() {
        return true;
    public boolean isAccountNonLocked() {
    public boolean isCredentialsNonExpired() {
    public boolean isEnabled() {
}

配置mybatis-plus

首先,需要配置application.properties數(shù)據(jù)庫連接源。

spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://106.55.137.66:3306/security?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

server.port=80

其次,需要配置Mapper類,查詢數(shù)據(jù)庫獲取基本數(shù)據(jù)信息。

package security.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
import security.vo.User;
@Repository
public interface UserMapper extends BaseMapper<User> {
}

配置security配置類

package security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import security.config.handler.*;
import security.filter.TokenAuthFilter;
import security.filter.TokenLoginFilter;
import security.service.UserDetailService;
/**
 * security 配置類
 */
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)  // 方法增加權(quán)限
public class MyTokenSecurityConfig extends WebSecurityConfigurerAdapter {
    // 將 UserDetailService 注入,使其去查詢數(shù)據(jù)庫
    @Autowired
    private UserDetailService userDetailsService;
    // token 生成器
    @Autowired
    private TokenJwtManager tokenManager;
    // 自定義密碼加密解密
    @Autowired
    private DefaultPwdEndoder defaultPwdEndoder;
    // 未登錄handler
    @Autowired
    private MyUnAuthEntryPoint myUnAuthEntryPoint;
    // 無權(quán)限
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;
    //  登出handler處理
    @Autowired
    private MyLogoutHandler myLogoutHandler;
    // 登錄失敗
    @Autowired
    private LoginFailedHandler loginFailedHandler;
    // 登錄成功
    @Autowired
    private LoginSuccessHandler loginSuccessHandler;
    /**
     * 登錄時(shí),從數(shù)據(jù)庫獲取基本信息和權(quán)限信息
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 設(shè)置 userDetailsService 和 密碼解析
        auth.userDetailsService(userDetailsService).passwordEncoder(defaultPwdEndoder);
    }
    /**
     * 配置訪問過濾
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling()
                .authenticationEntryPoint(myUnAuthEntryPoint) // 未登錄 handler
                .accessDeniedHandler(myAccessDeniedHandler) // 無權(quán)限
                .and().csrf().disable() // 關(guān)閉 csrf 跨域請求
                .formLogin()
                .loginProcessingUrl("/user/login")  // 設(shè)定登錄請求接口
                .usernameParameter("userName")
                .passwordParameter("passWord")
                //.successHandler(loginSuccessHandler) // 因?yàn)橛辛?TokenLoginFilter 配置過濾器,此處配置沒用
                //.failureHandler(loginFailedHandler) // 因?yàn)橛辛?TokenLoginFilter 配置過濾器,此處配置沒用
                .permitAll()
                .and()
                .authorizeRequests() // 請求設(shè)置
                .antMatchers("/test").permitAll() // 配置不需要認(rèn)證的接口
                .anyRequest().authenticated() // 任何請求都需要認(rèn)證
                .and()
                .logout() // logout設(shè)定
                .logoutUrl("/logouts")  //退出請求  /logouts 未定義,交給自定義handler實(shí)現(xiàn)功能
                .addLogoutHandler(myLogoutHandler) // 登出 myLogoutHandler 處理
                .and()
                .addFilter(new TokenLoginFilter(tokenManager,authenticationManager())) // 認(rèn)證交給 自定義 TokenLoginFilter 實(shí)現(xiàn)
                .addFilter(new TokenAuthFilter(authenticationManager(),tokenManager))
                .httpBasic();
    }
    /**
     * 配置不需要驗(yàn)證的訪問路徑
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        //web.ignoring().antMatchers("/test","/user/login");
        web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
    }
}

配置幾個(gè)測試接口

package security.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
    @RequestMapping("/test")
    public String test(){
        return "不需要認(rèn)證就能訪問";
    }
}
package security.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
    @RequestMapping("/user/test1")
    @PreAuthorize("hasAnyAuthority('admin','user')")
    public String test1(){
        return "需要認(rèn)證的 /user/test1";
    }
    @RequestMapping("/user/test2")
    @PreAuthorize("hasAnyAuthority('test')")
    public String test2(){
        return "需要認(rèn)證的 /user/test2";
}

Md5加密工具類

package security.utils;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/**
 * 加密工具類
 */
public class Md5Utils {
    public static String md5(String str) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(str.getBytes());
            byte b[] = md.digest();
            str = byteToStr(b);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }
    public static String byteToStr(byte[] b){
        int i;
        StringBuffer buf = new StringBuffer("");
        for (int offset = 0; offset < b.length; offset++) {
            i = b[offset];
            //System.out.println(i);
            if (i < 0)
                i += 256;
            if (i < 16)
                buf.append("0");
            buf.append(Integer.toHexString(i));
        return buf.toString();
    /**
     * 傳入文本內(nèi)容,返回 SHA-256 串
     *
     * @param strText
     * @return
     */
    public static String SHA256(final String strText)
    {
        return SHA(strText, "SHA-256");
    public static String SHA1(final String strText)
        return SHA(strText, "SHA-1");
     * 傳入文本內(nèi)容,返回 SHA-512 串
    public static String SHA512(final String strText)
        return SHA(strText, "SHA-512");
     * 字符串 SHA 加密
    private static String SHA(final String strText, final String strType)
        // 返回值
        String strResult = null;
        // 是否是有效字符串
        if (strText != null && strText.length() > 0)
        {
            try
            {
                // SHA 加密開始
                MessageDigest messageDigest = MessageDigest.getInstance(strType);
                // 傳入要加密的字符串
                messageDigest.update(strText.getBytes("utf-8"));
                // 得到 byte 類型的結(jié)果
                byte byteBuffer[] = messageDigest.digest();
                strResult = byteToStr(byteBuffer);
            }
            catch (NoSuchAlgorithmException e)
                e.printStackTrace();
            }catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
        return strResult;
    public static String base64(String str){
        String baseStr = null;
        Base64.Encoder encoder = Base64.getEncoder();
        byte[] textByte;
            textByte = str.getBytes("UTF-8");
            baseStr = encoder.encodeToString(textByte);
        } catch (UnsupportedEncodingException e) {
        return baseStr;
    public static void main(String[] args) {
        String password = "bunana1";
        System.out.println(md5(password));
        //String base64 = base64(sha512);
        //System.out.println(base64);
        //String pwd1 = md5(base64);
        //System.out.println(pwd1);
}

測試

測試采取ApiPost 工具,讓測試更接近前后分離。

首先測試登錄

Post
localhost/user/login

賬號(hào)密碼有一個(gè)不對時(shí)。

在這里插入圖片描述

正確的賬號(hào)密碼

在這里插入圖片描述

測試存在權(quán)限的接口

localhost/user/test1

在這里插入圖片描述

測試不存在權(quán)限的接口

localhost/user/test2

在這里插入圖片描述

測試登出

localhost/logouts

在這里插入圖片描述

測試不需要權(quán)限的接口

localhost/test

在這里插入圖片描述

數(shù)據(jù)庫sql腳本

CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, -- 主鍵
  `username` varchar(255) DEFAULT NULL,    -- 用戶名
  `password` varchar(255) DEFAULT NULL,    -- 用戶密碼
  `enabled` tinyint(1) DEFAULT '1',        -- 是否啟用 1-啟用 0-未啟用
  `locked` tinyint(1) DEFAULT '0',         -- 是否被鎖 1-已鎖 0-未鎖
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

數(shù)據(jù)為:

insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS","1babad058e03c5296a94a5a8d7d6dd8a",1,0); -- bunana 的md5 值
insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS2","0b13310f8db2dc22e7ddd0cdc5f0a61a",1,0); -- bunana1 的md5 值
insert INTO user(username,password,enabled,locked) VALUES("xiangjiaoSS3","b3fbcd9c9d97e47f263a19a0e01efc7d",1,0); -- bunana2 的md5 值

在這里插入圖片描述

代碼下載

springboot-security-10-qianhou

gitee 代碼下載地址

到此這篇關(guān)于Spring Security前后分離校驗(yàn)token的文章就介紹到這了,更多相關(guān)Spring Security校驗(yàn)token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?并發(fā)編程之ForkJoin框架

    Java?并發(fā)編程之ForkJoin框架

    這篇文章主要為大家介紹了Java?ForkJoin框架,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助,希望能夠給你帶來幫助
    2021-11-11
  • Java使用wait/notify實(shí)現(xiàn)線程間通信上篇

    Java使用wait/notify實(shí)現(xiàn)線程間通信上篇

    wait()和notify()是直接隸屬于Object類,也就是說所有對象都擁有這一對方法,下面這篇文章主要給大家介紹了關(guān)于使用wait/notify實(shí)現(xiàn)線程間通信的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • Java手把手必會(huì)的實(shí)例漢諾塔講解練習(xí)

    Java手把手必會(huì)的實(shí)例漢諾塔講解練習(xí)

    漢諾塔,傳說神在創(chuàng)造世界的時(shí)候做了三根金剛石柱子,并在一個(gè)教塔里留下了三根金剛石棒,第一根上面從上到下套著64個(gè)按從小到大排列的金盤,神命令廟里的眾僧將它們一個(gè)個(gè)地從這根金剛石棒搬到另一根金剛石棒上,大盤不能放在小盤上。最后64個(gè)金盤仍然要按從小到大排列
    2021-09-09
  • Java基于Calendar類輸出指定年份和月份的日歷代碼實(shí)例

    Java基于Calendar類輸出指定年份和月份的日歷代碼實(shí)例

    這篇文章主要介紹了Java 使用Calendar類輸出指定年份和月份的日歷,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • 基于Spring AOP @AspectJ進(jìn)階說明

    基于Spring AOP @AspectJ進(jìn)階說明

    這篇文章主要介紹了基于Spring AOP @AspectJ進(jìn)階說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Spring之IOC底層原理詳解

    Spring之IOC底層原理詳解

    這篇文章主要介紹了Spring之IOC底層原理,內(nèi)容詳細(xì),文章簡單易懂,具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-01-01
  • 關(guān)于Java?float和double精度范圍大小

    關(guān)于Java?float和double精度范圍大小

    這篇文章主要介紹了關(guān)于Java?float和double精度范圍大小,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java實(shí)現(xiàn)發(fā)送郵件功能時(shí)碰到的坑

    Java實(shí)現(xiàn)發(fā)送郵件功能時(shí)碰到的坑

    之前用163郵箱發(fā)郵件時(shí)明明是成功的,但是使用中國移動(dòng)自己的郵箱時(shí),無論如何在linux服務(wù)器中都發(fā)送不成功。下面小編給大家說下我是怎么解決的,一起看下吧
    2016-06-06
  • 基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析

    基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析

    這篇文章主要介紹了基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 深入SQLite多線程的使用總結(jié)詳解

    深入SQLite多線程的使用總結(jié)詳解

    本篇文章是對SQLite多線程的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05

最新評論