久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

混合身份驗證 - 基于 Spring MVC 會話 + 基于 JWT 令牌

Hybrid authentication - Spring MVC session based + JWT token based(混合身份驗證 - 基于 Spring MVC 會話 + 基于 JWT 令牌)
本文介紹了混合身份驗證 - 基于 Spring MVC 會話 + 基于 JWT 令牌的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

我有一種情況,我正在使用 Spring MVC(jsp、控制器、服務、dao)和基于會話的身份驗證.但是現在我將幾個 url 用作 RESTful Web 服務來進行集成.

I have a situation, I am using Spring MVC (jsp, controllers, service, dao) and session based authentication. But now few urls I am using as a RESTful Web service for integration purpose.

僅對于那些請求,我需要使用基于令牌(例如 JWT)的身份驗證.

For those requests only, I need to use token (for eg JWT) based authentication.

那么,有沒有可能我可以在同一個項目中使用這兩種類型的身份驗證.

So, is there any possibility that I can use both type of authentication within same project.

推薦答案

有沒有可能我可以在同一個項目中使用這兩種類型的身份驗證.

is there any possibility that I can use both type of authentication within same project.

是的,你可以.通過具有兩個身份驗證處理過濾器.

Yes you can. By having two authentication processing filters.

Filter - 1:用于 Rest API (JwtAuthTokenFilter),它應該是無狀態的,并由每次在請求中發送的授權令牌標識.
Filter - 2:你需要另一個過濾器(UsernamePasswordAuthenticationFilter) 默認情況下,如果你通過 http.formLogin() 配置它,spring-security 會提供這個.這里每個請求都由關聯的會話(JSESSIONID cookie)標識.如果請求不包含有效會話,那么它將被重定向到身份驗證入口點(例如:登錄頁面).

Filter - 1: for Rest API (JwtAuthTokenFilter) which should be stateless and identified by Authorization token sent in request each time.
Filter - 2: You need another filter (UsernamePasswordAuthenticationFilter) By default spring-security provides this if you configure it by http.formLogin(). Here each request is identified by the session(JSESSIONID cookie) associated. If request does not contain valid session then it will be redirected to authentication-entry-point (say: login-page).

api-url-pattern    = "/api/**"
webApp-url-pattern = "/**"

工作原理

  • 帶有 /api/** 的 URL 將通過 JwtAuthTokenFilter 傳遞,它將讀取令牌,如果它具有有效令牌,則設置身份驗證對象和鏈繼續.如果它沒有有效的請求,那么鏈會被破壞并且響應將被發送 401(未授權)狀態.

    How it works

    • URL's with /api/** will be passed through JwtAuthTokenFilter where it will read the token and if it has valid token, sets authentication object and chain continues. If it does not have the valid request then chain gets broken and response will be sent with 401(Unauthorized) status.

      /api/** 以外的 URL 將由 UsernamePasswordAuthenticationFilter 處理 [這是由 .formLogin() configuration] 它將檢查有效會話,如果它不包含有效會話,它將重定向到 logoutSuccessUrl 配置.

      URL's other than /api/** will be handled by UsernamePasswordAuthenticationFilter [which is default in spring security configured by .formLogin() configuration] It will check for valid session, if it does not contain the valid session it will redirects to logoutSuccessUrl configured.

      注意:您的 Web 應用程序無法使用現有會話訪問 API.您有什么選擇是使用 Jwt 令牌從 Web 應用程序訪問 API.

      Note: Your Webapp can not access APIs by using existing session. What option you have is to use Jwt token to access API from Web application.

      如何配置

      實現兩種不同的身份驗證處理過濾器,您應該以不同的順序配置多個 http 安全配置
      可以通過在安全配置類中聲明靜態類來配置多個 http 安全配置,如下所示.
      (盡管 OP 要求概念明智地呈現代碼明智.它可能會幫助您參考)

      @Configuration
      @EnableWebSecurity
      @ComponentScan(basePackages = "com.gmail.nlpraveennl")
      public class SpringSecurityConfig
      {
          @Bean
          public PasswordEncoder passwordEncoder() 
          {
              return new BCryptPasswordEncoder();
          }
      
          @Configuration
          @Order(1)
          public static class RestApiSecurityConfig extends WebSecurityConfigurerAdapter
          {
              @Autowired
              private JwtAuthenticationTokenFilter jwtauthFilter;
      
              @Override
              protected void configure(HttpSecurity http) throws Exception
              {
                  http
                      .csrf().disable()
                      .antMatcher("/api/**")
                      .authorizeRequests()
                      .antMatchers("/api/authenticate").permitAll()
                      .antMatchers("/api/**").hasAnyRole("APIUSER")
                  .and()
                      .addFilterBefore(jwtauthFilter, UsernamePasswordAuthenticationFilter.class);
      
                  http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
              }
          }
      
          @Configuration
          @Order(2)
          public static class LoginFormSecurityConfig extends WebSecurityConfigurerAdapter
          {
              @Autowired
              private PasswordEncoder passwordEncoder;
      
              @Autowired
              public void configureInMemoryAuthentication(AuthenticationManagerBuilder auth) throws Exception
              {
                  auth.inMemoryAuthentication().withUser("admin").password(passwordEncoder.encode("admin@123#")).roles("ADMIN");
              }
      
              @Override
              protected void configure(HttpSecurity http) throws Exception
              {
                  http
                      .csrf().disable()
                      .antMatcher("/**").authorizeRequests()
                      .antMatchers("/resources/**").permitAll()
                      .antMatchers("/**").hasRole("ADMIN")
                  .and().formLogin();
      
                  http.sessionManagement().maximumSessions(1).expiredUrl("/customlogin?expired=true");
              }
          }
      }
      

      Jwt 身份驗證令牌過濾器

      @Component
      public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
      {
          @Autowired
          private JwtTokenUtil jwtTokenUtil;
      
          @Override
          protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException
          {
              final String header = request.getHeader("Authorization");
      
              if (header != null && header.startsWith("Bearer ")) 
              {
                  String authToken = header.substring(7);
                  System.out.println(authToken);
      
                  try
                  {
                      String username = jwtTokenUtil.getUsernameFromToken(authToken);
                      if (username != null && SecurityContextHolder.getContext().getAuthentication() == null)
                      {
                          if (jwtTokenUtil.validateToken(authToken, username))
                          {
                              List<GrantedAuthority> authList = new ArrayList<>();
                              authList.add(new SimpleGrantedAuthority("ROLE_APIUSER"));
      
                              UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(username, null, authList);
                              usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
      
                              SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                          }
                      }
                  }
                  catch (Exception e)
                  {
                      System.out.println("Unable to get JWT Token, possibly expired");
                  }
              }
      
              chain.doFilter(request, response);
          }
      }
      

      Jwt 令牌工具類

      @Component
      public class JwtTokenUtil implements Serializable
      {
          private static final long   serialVersionUID    = 8544329907338151549L;
          public static final long    JWT_TOKEN_VALIDITY  = 5 * 60 * 60;
          private String              secret              = "my-secret";
      
          public String getUsernameFromToken(String token)
          {
              return getClaimFromToken(token, Claims::getSubject);
          }
      
          public Date getExpirationDateFromToken(String token)
          {
              return getClaimFromToken(token, Claims::getExpiration);
          }
      
          public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver)
          {
              final Claims claims = getAllClaimsFromToken(token);
              return claimsResolver.apply(claims);
          }
      
          private Claims getAllClaimsFromToken(String token)
          {
              return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
          }
      
          private Boolean isTokenExpired(String token)
          {
              final Date expiration = getExpirationDateFromToken(token);
              return expiration.before(new Date());
          }
      
          public String generateToken(String username)
          {
              Map<String, Object> claims = new HashMap<>();
              return doGenerateToken(claims, username);
          }
      
          private String doGenerateToken(Map<String, Object> claims, String subject)
          {
              return "Bearer "+Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                      .setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000)).signWith(SignatureAlgorithm.HS512, secret).compact();
          }
      
          public Boolean validateToken(String token, String usernameFromToken)
          {
              final String username = getUsernameFromToken(token);
              return (username.equals(usernameFromToken) && !isTokenExpired(token));
          }
      }
      

      Dispatcher Servlet 配置

      @Configuration
      @EnableWebMvc
      @ComponentScan(basePackages = "com.gmail.nlpraveennl") //Do not skip componentscan
      public class ServletConfiguration implements WebMvcConfigurer
      {
           @Bean
           public ViewResolver configureViewResolver() 
           {
               InternalResourceViewResolver viewResolve = new InternalResourceViewResolver();
               viewResolve.setPrefix("/WEB-INF/jsp/");
               viewResolve.setSuffix(".jsp");
      
               return viewResolve;
           }
      
          @Bean
          public ResourceBundleMessageSource messageSource()
          {
              ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
              messageSource.setBasename("messages");
              messageSource.setDefaultEncoding("UTF-8");
              messageSource.setUseCodeAsDefaultMessage(true);
              return messageSource;
          }
      
          @Override
          public void addResourceHandlers(ResourceHandlerRegistry registry)
          {
              registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
          }
      }
      

      以上解釋是一種實現,我已經在 我的另一個答案,你可以在這里參考

      Above explanation is one type of implementation, i have explained other type of implementation(where Rest APIs can be accessed by auth token as well as session) in my another answer which you can refer here

      這篇關于混合身份驗證 - 基于 Spring MVC 會話 + 基于 JWT 令牌的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

      【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How to wrap text around components in a JTextPane?(如何在 JTextPane 中的組件周圍環繞文本?)
MyBatis, how to get the auto generated key of an insert? [MySql](MyBatis,如何獲取插入的自動生成密鑰?[MySql])
Inserting to Oracle Nested Table in Java(在 Java 中插入 Oracle 嵌套表)
Java: How to insert CLOB into oracle database(Java:如何將 CLOB 插入 oracle 數據庫)
Why does Spring-data-jdbc not save my Car object?(為什么 Spring-data-jdbc 不保存我的 Car 對象?)
Use threading to process file chunk by chunk(使用線程逐塊處理文件)
主站蜘蛛池模板: 欧美日韩在线精品 | 国内在线视频 | 国产精品精品视频一区二区三区 | 国产亚洲欧美另类一区二区三区 | 国产高清美女一级a毛片久久w | 99精品免费在线观看 | 久久久久久久国产 | 欧美精品一区久久 | 中文字幕一页二页 | 国产成人精品一区二区三区四区 | 国产精品地址 | 国产在线1区| 国产精品一区二区三区四区五区 | 国产精品久久久久久久久久久久久 | 69av片| 亚洲精品久久久一区二区三区 | 成人在线一级片 | 激情a| 天天曰天天干 | 尤物在线精品视频 | 欧美日韩国产一区二区 | 国产在线网址 | 视频一区在线 | 免费国产视频 | 在线免费观看黄视频 | 亚洲伊人久久综合 | 福利视频日韩 | 高清黄色网址 | 精品国产欧美一区二区三区成人 | 992人人草 | 精品国产乱码久久久久久蜜柚 | 日韩二区三区 | 久久夜夜| 国产在线色| 欧美一区二区在线观看 | 97国产一区二区 | 亚洲精品日日夜夜 | 亚洲国产精久久久久久久 | 国产成人午夜精品影院游乐网 | 99精品久久久久久久 | 欧美一级淫片免费视频黄 |