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

SpringBoot+SpringSecurity+jwt實(shí)現(xiàn)驗(yàn)證

 更新時(shí)間:2022年07月28日 09:43:13   作者:南歸客_Kdream  
本文主要介紹了SpringBoot+SpringSecurity+jwt實(shí)現(xiàn)驗(yàn)證,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

記錄一下使用springSecurity實(shí)現(xiàn)jwt的授權(quán)方法,這方法可以實(shí)現(xiàn)權(quán)限的基本認(rèn)證。當(dāng)然這個(gè)案例還有許多的問題,不過(guò)還是先記錄一下。其他功能以后在補(bǔ)充。

建議工程創(chuàng)建流程

  • 創(chuàng)建 JwtTokenUtils
  • 創(chuàng)建 jwtAccessDeniedHandler 和 JwtAuthenticationEntryPoint
  • 創(chuàng)建 UserDetailsServiceImpl
  • 創(chuàng)建 JwtAuthenticationFilter
  • 配置 Security信息
  • 啟動(dòng)類的信息

環(huán)境

  • springBoot 2.3.3
  • springSecurity 5.0
  • jjwt 0.91

pox.xml 文件主要信息

        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

目錄結(jié)構(gòu)信息

請(qǐng)忽略文件命名

jwtAccessDeniedHandler 和 JwtAuthenticationEntryPoint

這兩個(gè)類的作用是用戶訪問沒有授權(quán)資源和攜帶錯(cuò)誤token的錯(cuò)誤返回處理信息類,要使用這兩個(gè)類只需要在security的配置文件中配置一下就可以只用了

/**
 * @author Bxsheng
 * @blogAddress www.kdream.cn
 * @createTIme 2020/9/17
 * since JDK 1.8
 * 當(dāng)用戶在沒有授權(quán)的時(shí)候,返回的指定信息
 */
@Component
public class jwtAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        System.out.println("用戶訪問沒有授權(quán)資源");
        System.out.println(e.getMessage());
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e==null?"用戶訪問沒有授權(quán)資源":e.getMessage());

    }
}

/**
 * @author Bxsheng
 * @blogAddress www.kdream.cn
 * @createTIme 2020/9/17
 * since JDK 1.8
 */
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        System.out.println("用戶訪問資源沒有攜帶正確的token");
        System.out.println(e.getMessage());
        httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e==null?"用戶訪問資源沒有攜帶正確的token":e.getMessage());

    }
}

UserDetailsServiceImpl 登錄信息驗(yàn)證

該類直接繼承UserDetailsService 進(jìn)行登錄信息驗(yàn)證,在輸入賬戶密碼進(jìn)行登錄的時(shí)候,會(huì)進(jìn)入這個(gè)類進(jìn)行驗(yàn)證信息。

當(dāng)然我這里是直接使用了寫死的密碼,正常應(yīng)該從數(shù)據(jù)庫(kù)中獲取用戶的信息和權(quán)限信息

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        //直接寫死數(shù)據(jù)信息,可以在這里獲取數(shù)據(jù)庫(kù)的信息并進(jìn)行驗(yàn)證

        UserDetails userDetails  = User.withUsername(s).password(new BCryptPasswordEncoder().encode("123456"))
                .authorities("bxsheng").build();
        return userDetails;
    }
}

JwtTokenUtils jwt包裝類

該類直接使用 slyh 的 [SpringBoot+JWT實(shí)現(xiàn)登錄權(quán)限控制(代碼))](( http://www.dbjr.com.cn/article/257119.htm)的文章里面的類。

package cn.kdream.securityjwt.utlis;

import io.jsonwebtoken.*;

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

/**
 * @author Bxsheng
 * @blogAddress www.kdream.cn
 * @createTIme 2020/9/16
 * since JDK 1.8
 */
public class JwtTokenUtils {
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String SECRET = "jwtsecret";
    public static final String ISS = "echisan";

    private static final Long EXPIRATION = 60 * 60 * 3L; //過(guò)期時(shí)間3小時(shí)

    private static final String ROLE = "role";

    //創(chuàng)建token
    public static String createToken(String username, String role, boolean isRememberMe){
        Map map = new HashMap();
        map.put(ROLE, role);
        return Jwts.builder()
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .setClaims(map)
                .setIssuer(ISS)
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
                .compact();
    }

    //從token中獲取用戶名(此處的token是指去掉前綴之后的)
    public static String getUserName(String token){
        String username;
        try {
            username = getTokenBody(token).getSubject();
        } catch (    Exception e){
            username = null;
        }
        return username;
    }

    public static String getUserRole(String token){
        return (String) getTokenBody(token).get(ROLE);
    }

    private static Claims getTokenBody(String token){
        Claims claims = null;
        try{
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch(ExpiredJwtException e){
            e.printStackTrace();
        } catch(UnsupportedJwtException e){
            e.printStackTrace();
        } catch(MalformedJwtException e){
            e.printStackTrace();
        } catch(SignatureException e){
            e.printStackTrace();
        } catch(IllegalArgumentException e){
            e.printStackTrace();
        }
        return claims;
    }

    //是否已過(guò)期
    public static boolean isExpiration(String token){
        try{
            return getTokenBody(token).getExpiration().before(new Date());
        } catch(Exception e){
            System.out.println(e.getMessage());
        }
        return true;
    }
}

JwtAuthenticationFilter 自定義驗(yàn)證jwt

該類直接使用 slyh 的 [SpringBoot+JWT實(shí)現(xiàn)登錄權(quán)限控制(代碼))](( http://www.dbjr.com.cn/article/257119.htm))的文章里面的類。

這個(gè)類主要的作用是驗(yàn)證jwt信息 ,主要攜帶了token請(qǐng)求過(guò)來(lái),解析jwt并設(shè)置在security的上下文中。這樣做的其中一個(gè)目的是你獲得了token中攜帶的權(quán)限信息,并保存在上下文中。你就可以對(duì)用戶進(jìn)行權(quán)限認(rèn)證了

/**
 * @author Bxsheng
 * @blogAddress www.kdream.cn
 * @createTIme 2020/9/16
 * since JDK 1.8
 */
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
        //如果請(qǐng)求頭中沒有Authorization信息則直接放行了
        if(tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)){
            chain.doFilter(request, response);
            return;
        }
        //如果請(qǐng)求頭中有token,則進(jìn)行解析,并且設(shè)置認(rèn)證信息
        if(!JwtTokenUtils.isExpiration(tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX,""))){
            //設(shè)置上下文
            UsernamePasswordAuthenticationToken authentication = getAuthentication(tokenHeader);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        super.doFilterInternal(request, response, chain);
    }

    //獲取用戶信息
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader){
        String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");
        String username = JwtTokenUtils.getUserName(token);
        // 獲得權(quán)限 添加到權(quán)限上去
        String role = JwtTokenUtils.getUserRole(token);
        List<GrantedAuthority> roles = new ArrayList<GrantedAuthority>();
        roles.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return role;
            }
        });
        if(username != null){
            return new UsernamePasswordAuthenticationToken(username, null,roles);
        }
        return null;
    }

}

security的配置信息

@EnableGlobalMethodSecurity(prePostEnabled = true) 開啟prePostEnabled注解方式授權(quán)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityJwtConfig extends WebSecurityConfigurerAdapter {


    @Autowired
    private jwtAccessDeniedHandler jwtAccessDeniedHandler;

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       http.cors().and().csrf().disable().authorizeRequests()
               .antMatchers(HttpMethod.OPTIONS,"/**")
               .permitAll()
               .antMatchers("/").permitAll()
               //login 不攔截
               .antMatchers("/login").permitAll()
               .anyRequest().authenticated()
               //授權(quán)
               .and()
               // 禁用session
               .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
       // 使用自己定義的攔截機(jī)制,攔截jwt
        http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class)
        //授權(quán)錯(cuò)誤信息處理
                .exceptionHandling()
                //用戶訪問資源沒有攜帶正確的token
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)
                //用戶訪問沒有授權(quán)資源
                .accessDeniedHandler(jwtAccessDeniedHandler);
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        //使用的密碼比較方式
        return  new BCryptPasswordEncoder();
    }

}

啟動(dòng)類

我在啟動(dòng)類中配置了三個(gè)方法,一個(gè)是用來(lái)進(jìn)行登錄信息的,另外兩個(gè)設(shè)置了需要權(quán)限訪問

@SpringBootApplication
@RestController
public class SecurityJwtApplication {

    private final AuthenticationManagerBuilder authenticationManagerBuilder;

    public SecurityJwtApplication(AuthenticationManagerBuilder authenticationManagerBuilder) {
        this.authenticationManagerBuilder = authenticationManagerBuilder;
    }

    public static void main(String[] args) {
        SpringApplication.run(SecurityJwtApplication.class, args);
    }



    @GetMapping("/")
    public String index(){
        return "security jwt";
    }

    @PostMapping("/login")
    public String login(@RequestParam String u,@RequestParam String p){
        // 登陸驗(yàn)證
        UsernamePasswordAuthenticationToken token =
                new UsernamePasswordAuthenticationToken(u, p);
        Authentication authentication = authenticationManagerBuilder.getObject().authenticate(token);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //創(chuàng)建jwt信息
        String token1 = JwtTokenUtils.createToken(u,"bxsheng", true);
        return token1;
    }

    @GetMapping("/role")
    @PreAuthorize("hasAnyAuthority('bxsheng')")
    public String roleInfo(){
        return "需要獲得bxsheng權(quán)限,才可以訪問";
    }

    @GetMapping("/roles")
    @PreAuthorize("hasAnyAuthority('kdream')")
    public String rolekdream(){
        return "需要獲得kdream權(quán)限,才可以訪問";
    }
}

效果

直接訪問需要授權(quán)的用戶信息

直接沒有使用token直接訪問只要授權(quán)的資源信息,會(huì)進(jìn)入JwtAuthenticationEntryPoint 類

獲取token

訪問在啟動(dòng)類中的login方法,獲取token信息

因?yàn)槲沂褂昧斯潭ǖ拿艽a,所以在使用錯(cuò)誤的密碼訪問的時(shí)候,可以在springboot的全局異常處理中捕獲到異常信息

/**
 * @author Bxsheng
 * @blogAddress www.kdream.cn
 * @createTIme 2020/9/17
 * since JDK 1.8
 */
@RestControllerAdvice
public class Error {
    @ExceptionHandler(BadCredentialsException.class)
    public void badCredentialsException(BadCredentialsException e){
        System.out.println(e.getMessage());//用戶名或密碼錯(cuò)誤

       // throw new  BadCredentialsException(e.getMessage());
    }
}

正確的獲取token,并進(jìn)行受保護(hù)的資源訪問

里面有寫死的bxsheng權(quán)限信息,所以正常是可以獲取bxsheng標(biāo)識(shí)的資源信息的。

成功獲取信息

嘗試獲取無(wú)權(quán)限資源信息

使用token直接訪問無(wú)權(quán)限資源信息,會(huì)進(jìn)入jwtAccessDeniedHandler 類

至此應(yīng)該可以說(shuō)算完成簡(jiǎn)單的權(quán)限管理了。

到此這篇關(guān)于SpringBoot+SpringSecurity+jwt實(shí)現(xiàn)驗(yàn)證的文章就介紹到這了,更多相關(guān)SpringBoot  SpringSecurity jwt 驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解MyBatis模糊查詢LIKE的三種方式

    詳解MyBatis模糊查詢LIKE的三種方式

    模糊查詢也是數(shù)據(jù)庫(kù)SQL中使用頻率很高的SQL語(yǔ)句,這篇文章主要介紹了詳解MyBatis模糊查詢LIKE的三種方式,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-10-10
  • Spring?IOC?xml方式進(jìn)行工廠Bean操作詳解

    Spring?IOC?xml方式進(jìn)行工廠Bean操作詳解

    這篇文章主要介紹了Spring?IOC?xml方式進(jìn)行工廠Bean操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-01-01
  • SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理

    SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理

    FastDFS是一個(gè)開源的輕量級(jí)分布式文件系統(tǒng),它對(duì)文件進(jìn)行管理,功能包括:文件存儲(chǔ)、文件同步、文件上傳、文件下載等,解決了大容量存儲(chǔ)和負(fù)載均衡的問題,本文介紹了SpringBoot整合FastDFS中間件實(shí)現(xiàn)文件分布管理,需要的朋友可以參考下
    2024-08-08
  • java設(shè)計(jì)模式筆記之裝飾模式

    java設(shè)計(jì)模式筆記之裝飾模式

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計(jì)模式筆記之裝飾模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • SpringBoot實(shí)現(xiàn)JWT 認(rèn)證的項(xiàng)目實(shí)踐

    SpringBoot實(shí)現(xiàn)JWT 認(rèn)證的項(xiàng)目實(shí)踐

    本文介紹了Spring Boot中實(shí)現(xiàn)JWT認(rèn)證,并介紹了擴(kuò)展JWT認(rèn)證功能,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-08-08
  • 關(guān)于Java內(nèi)存訪問重排序的研究

    關(guān)于Java內(nèi)存訪問重排序的研究

    文章主要介紹了重排序現(xiàn)象及其在多線程編程中的影響,包括內(nèi)存可見性問題和Java內(nèi)存模型中對(duì)重排序的規(guī)則
    2025-01-01
  • 2021年最新Redis面試題匯總(3)

    2021年最新Redis面試題匯總(3)

    在程序員面試過(guò)程中redis相關(guān)的知識(shí)是常被問到的話題。這篇文章主要介紹了幾道Redis面試題,整理一下分享給大家,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 利用Java實(shí)現(xiàn)讀寫bmp文件的示例代碼

    利用Java實(shí)現(xiàn)讀寫bmp文件的示例代碼

    位圖(Bitmap,BMP)是一種最原始、最簡(jiǎn)單的圖像文件格式,由微軟和 IBM 在 1980 年代聯(lián)合制定,用于 Windows 操作系統(tǒng),本項(xiàng)目旨在用純 Java 從零實(shí)現(xiàn)一個(gè)輕量級(jí)的 BMP 文件讀寫庫(kù),需要的朋友可以參考下
    2025-05-05
  • Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解

    這篇文章主要為大家介紹了Java語(yǔ)言中的文件數(shù)據(jù)流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • java使用BeanUtils.copyProperties方法對(duì)象復(fù)制同名字段類型不同賦值為空問題解決方案

    java使用BeanUtils.copyProperties方法對(duì)象復(fù)制同名字段類型不同賦值為空問題解決方案

    這篇文章主要給大家介紹了關(guān)于java使用BeanUtils.copyProperties方法對(duì)象復(fù)制同名字段類型不同賦值為空問題的解決方案,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-11-11

最新評(píng)論