《代码实例》jwt参与用户凭证方式,生成jwt,security整合jwt

Posted 欧皇夏老板

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《代码实例》jwt参与用户凭证方式,生成jwt,security整合jwt相关的知识,希望对你有一定的参考价值。

config
CorsConfig.java

package com.woniu.springsecurityday01.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig implements WebMvcConfigurer 
    @Override
    public void addCorsMappings(CorsRegistry registry) 
        // 设置允许跨域的路径
        registry.addMapping("/**")
                // 设置允许跨域请求的域名
                .allowedOriginPatterns("*")
                // 是否允许cookie
                .allowCredentials(false)
                // 设置允许的请求方式
                .allowedMethods("GET", "POST", "DELETE", "PUT")
                // 设置允许的header属性
                .allowedHeaders("*")
                // 跨域允许时间
                .maxAge(3600);
    


SecurityConfig.java

package com.woniu.springsecurityday01.config;

import com.woniu.springsecurityday01.dao.UserDao;
import com.woniu.springsecurityday01.handler.*;
import com.woniu.springsecurityday01.service.SecurityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,jsr250Enabled = true,prePostEnabled=true)//作用:开启注解式鉴权
public class SecurityConfig extends WebSecurityConfigurerAdapter 

    @Autowired
    private SecurityService securityService;

    @Autowired
    private LoginSuccessHandler loginSuccessHandler;

    @Autowired
    private JWTFilter jwtFilter;

    /**
     * 认证
     * @param auth
     * @throws Exception
     */
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 
        //BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
        //String encode=passwordEncoder.encode("123");
        //自定义用户名和密码
       // auth.inMemoryAuthentication().withUser("admin").password(encode).roles("admin");
        auth.userDetailsService(securityService);
    

    /**
     * 自定义登录页面
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception 
        http.formLogin() //告诉框架自定义页面
                .loginPage("/login.html") //登录页面地址
                .loginProcessingUrl("/dologin")//对应表单提交的action
                .successHandler(loginSuccessHandler)
                .failureHandler(new LoginFailHandler())
                .permitAll();//对上面两个请求放行
        //1.无权限2.未登录而登录
        http.exceptionHandling()
                .accessDeniedHandler(new NOAuthHandler())
                .authenticationEntryPoint(new NoLoginHandler());
        /**
         * 授权
         */
        http.authorizeRequests()
                //.antMatchers("/hello").hasAuthority("stu:query")
                //.antMatchers("/delete").hasAuthority("stu:query")
                //.antMatchers("/hello").hasAnyAuthority("stu:query","hello")
                //.antMatchers("/hello").hasRole("stu:query")
                //.antMatchers("/delete").permitAll() //配置免拦截方法

                .anyRequest().authenticated();//所有请求都拦截
        /**
         * 把jwtfilter注入进来
         */
        http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);

        /**
         * 把session禁掉
         */
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        //跨站脚本攻击关闭
        http.csrf().disable();

        //允许跨域请求
        http.cors();

    

    @Bean
    public PasswordEncoder passwordEncoder()
        return new BCryptPasswordEncoder();
    


controller
HelloController.java

package com.woniu.springsecurityday01.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
/**
 * @RequestBody+@Controller=@RestController
 */
public class HelloController 


    //@Secured("ROLE_stu:query")
    //@PermitAll()
    @PreAuthorize("hasAuthority('stu:query')")
    @RequestMapping("/hello")
    public String hello()
        return "hello security";
    

    @RequestMapping("/delete")
    public String delete()
        return "hello delete";
    




dao
UserDao.java

package com.woniu.springsecurityday01.dao;

import com.woniu.springsecurityday01.domain.Users;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDao 
    /**
     * 根据账号查用户信息及其权限
     */
    Users getUserInfoByAccount(String account);


domain
Users.java

package com.woniu.springsecurityday01.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Users 

    private Integer id;

    private String username;

    private String account;

    private String password;

    private List<String> anth;//该用户拥有的权限


handler
JWTFilter.java

package com.woniu.springsecurityday01.handler;

import com.woniu.springsecurityday01.service.SecurityService;
import com.woniu.springsecurityday01.util.JWTUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

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.Map;
import java.util.concurrent.TimeUnit;

/**
 * 校验jwt
 *
 * 1:判断请求是否携带jwt
 *  否:放行不处理
 *  是:走到第二步
 * 2:对前端传过来的jwt解密
 *  否:放行不处理
 *  是:走到第三步
 * 3: 获取redis的jwt
 *  获取不到:放行不处理
 *  获取到:走到第四步
 * 4:对比jwt
 *  否:放行不处理
 *  是:走到第五步
 * 5:给jwt续期
 *
 */
@Component
public class JWTFilter extends OncePerRequestFilter 
    /**
     * StringRedisTemplate和RedisTemplate区别
     */
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SecurityService securityService;
    @SneakyThrows
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain)
            throws ServletException, IOException 
        /**
         * * 1:判断请求是否携带jwt
         *  *  否:放行不处理
         *  *  是:走到第二步
         */
        String jwt=request.getHeader("jwt");
        if(jwt==null)
            //交给下一个过滤器处理
            filterChain.doFilter(request,response);
            return;
        

        /**
         * 2:对前端传过来的jwt解密
         *  *  否:放行不处理
         *  *  是:走到第三步
         */
        if(!JWTUtil.decode(jwt))
            filterChain.doFilter(request,response);
            return;
        
        /**
         * 3: 获取redis的jwt
         *  *  获取不到:放行不处理
         *  *  获取到:走到第四步
         */
        Map payLoad = JWTUtil.getPayLoad(jwt);
        String username=(String)payLoad.get("username");
        String redisJwt = redisTemplate.opsForValue().get("jwt:" + username);
        if(redisJwt==null)
            filterChain.doFilter(request,response);
            return;
        
        /**
         * 4:对比jwt
         *  *  否:放行不处理
         *  *  是:走到第五步
         */
        if(!jwt.equals(redisJwt))
            filterChain.doFilter(request,response);
            return;
        
        /**
         * 5:给jwt续期
         */
        redisTemplate.opsForValue().set("jwt:"+ username,jwt,30, TimeUnit.MINUTES);

        //把用户信息放到security容器中去
        UserDetails userDetails = securityService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken upa=
                new UsernamePasswordAuthenticationToken(userDetails.getUsername(),
                                                        userDetails.getPassword(),
                                                        userDetails.getAuthorities());
        //把信息放到security容器中去
        SecurityContextHolder.getContext().setAuthentication(upa);

        filterChain.doFilter(request,response);

    


LoginSuccessHandler.java

package com.woniu.springsecurityday01.handler;

import com.alibaba.fastjson.JSON;
import com.woniu.springsecurityday01.util.JWTUtil;
import com.woniu.springsecurityday01.util.ResponseResult;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
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.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 登录成功处理器
 */
@Component
public class LoginSuccessHandler implements AuthenticationSuccessHandler 

    @Autowired
    private StringRedisTemplate redisTemplate;

    @SneakyThrows
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
                                        HttpServletResponse httpServletResponse,
                                        Authentication authentication)
            throws IOException, ServletException 

        httpServletResponse.setContentType("application/json;charset=UTF-8");

        User user=(User) authentication.getPrincipal();
        String username= user.getUsername();
        Map map=new HashMap();
        map.put("username",username);
        String jwt= JWTUtil.createJWT(map);
        //拿jwt干那些事情? 1:放到redis,2:把jwt传到前端
        redisTemplate.opsForValue().set("jwt:"+username,jwt,30, TimeUnit.MINUTES);


        httpServletResponse.getWriter().write(JSON.toJSONString( new ResponseResult().ok(jwt)));

    


其他几个认证同上篇

service
SecurityService.java

package com.woniu.springsecurityday01.service;

import com.woniu.springsecurityday01.dao.UserDao;
import com.woniu.springsecurityday01.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class SecurityService implements UserDetailsService 
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private UserDao userDao;
    /**
     * username:页面传过来的用户名
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        Users userInfo=userDao.getUserInfoByAccount(username);
        if(userInfo!=null)
            String join =String.join(","

php Laravel Tymon JWT从凭证生成令牌

$credentials = $request->only('email', 'password');

$token = JWTAuth::attempt($credentials);

以上是关于《代码实例》jwt参与用户凭证方式,生成jwt,security整合jwt的主要内容,如果未能解决你的问题,请参考以下文章

php Laravel Tymon JWT从凭证生成令牌

生成 AR-JWT 令牌 [关闭]

jwt 实践应用以及特殊案例思考

Django JWT登录认证机制

Django JWT登录认证机制

用户登录鉴权JWT代码实现