zoukankan      html  css  js  c++  java
  • springboot+vue实现前后端分离之后端spring部分(spring boot 2.5.4/vue.js 3.2.4)

    一,前、后端项目的代码地址

    前端:
    https://gitee.com/liuhongdi/jwtweb
    后端:
    https://gitee.com/liuhongdi/jwtdemo

     说明:前端部分的安装第三方库等说明请参见:

    https://www.cnblogs.com/architectforest/p/15185275.html

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/
             或: https://gitee.com/liuhongdi

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,后端项目配置信息说明:

    1,pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.5.4</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.lhd</groupId>
        <artifactId>jwtdemo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>jwtdemo</name>
        <description>jwtdemo</description>
        <properties>
            <java.version>16</java.version>
        </properties>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--security begin-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <!--jjwt begin-->
            <dependency>
                <groupId>io.jsonwebtoken</groupId>
                <artifactId>jjwt</artifactId>
                <version>0.9.1</version>
            </dependency>
            <!--fastjson begin-->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.78</version>
            </dependency>
            <!--jaxb-->
            <dependency>
                <groupId>javax.xml.bind</groupId>
                <artifactId>jaxb-api</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-impl</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>com.sun.xml.bind</groupId>
                <artifactId>jaxb-core</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>javax.activation</groupId>
                <artifactId>activation</artifactId>
                <version>1.1.1</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>

    2,application.yml

    #server
    server:
      port: 8000
      error:
        include-stacktrace: always

     三,java代码说明

    1,controller/HomeController.java

    @Controller
    @RequestMapping("/home")
    public class HomeController {
    
        //session详情
        @GetMapping("/home")
        @ResponseBody
        public Result home() {
            Map<String, String> data = new HashMap<String, String>();
            data.put("username", SessionUtil.getCurrentUserName());
            data.put("userid", String.valueOf(SessionUtil.getCurrentUser().getUserid()));
            data.put("nickname", SessionUtil.getCurrentUser().getNickname());
            data.put("roles", SessionUtil.getCurrentUser().getAuthorities().toString());
            return Result.success(data);
        }
    }

    返回用户的session信息

    2,jwt/JwtAuthticationFilter.java

    @Component
    public class JwtAuthticationFilter implements Filter {
    
        @Resource
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private JwtTokenUtil jwtTokenUtil;
    
        @Autowired
        private JwtUserDetailsService userDetailsService;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("----------------AuthticationFilter init");
        }
        //过滤功能
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            //得到当前的url
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            String path = request.getServletPath();
            //如果是登录的url,需要进行验证
            if (path.equals("/auth/authenticate")) {
                 //得到请求的post参数
                String username = "";
                String password = "";
                try {
                    BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
                    StringBuffer sb=new StringBuffer();
                    String s=null;
                    while((s=br.readLine())!=null){
                        sb.append(s);
                    }
                    JSONObject jsonObject = JSONObject.parseObject(sb.toString());
                    username = jsonObject.getString("username");
                    password = jsonObject.getString("password");
                    //System.out.println("name:"+name+" age:"+age);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                String authResult = "";
                try{
                    authResult = authenticate(username,password);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if ("success".equals(authResult)) {
                    final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                    final String token = jwtTokenUtil.generateToken(userDetails);
                    Map<String, String> mapData = new HashMap<String, String>();
                    mapData.put("token", token);
                    ServletUtil.printRestResult(Result.success(mapData));
                } else if ("badcredential".equals(authResult)){
                    ServletUtil.printRestResult(Result.error(ResponseCode.LOGIN_FAIL));
                } else {
                    ServletUtil.printRestResult(Result.error(ResponseCode.ERROR));
                }
                return;
            } else {
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    
        @Override
        public void destroy() {
            System.out.println("----------------filter destroy");
        }
    
        //通过用户名密码进行验证
        private String authenticate(String username, String password) throws Exception {
            try {
                authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
                return "success";
            } catch (DisabledException e) {
                throw new Exception("USER_DISABLED", e);
            } catch (BadCredentialsException e) {
                System.out.println("BadCredentialsException");
                System.out.println(e.toString());
                return "badcredential";
            }
        }
    }

    说明:登录验证的url: /auth/authenticate是在这个filter中进行的

    3,jwt/JwtRequestFilter.java

    @Component
    public class JwtRequestFilter extends OncePerRequestFilter {
    
        @Autowired
        private JwtUserDetailsService jwtUserDetailsService;
    
        @Autowired
        private JwtTokenUtil jwtTokenUtil;
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
                throws ServletException, IOException {
            final String requestTokenHeader = request.getHeader("Authorization");
            String username = null;
            String jwtToken = null;
            // JWT Token 获取请求头部的 Bearer
            System.out.println("filter:header:"+requestTokenHeader);
            // only the Token
            if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
                //System.out.println("filter :requestTokenHeader not null and start with bearer");
                jwtToken = requestTokenHeader.substring(7);
                try {
                    username = jwtTokenUtil.getUsernameFromToken(jwtToken);
                } catch (IllegalArgumentException e) {
                    System.out.println("Unable to get JWT Token");
                } catch (ExpiredJwtException e) {
                    System.out.println("JWT Token has expired");
                } catch (MalformedJwtException e) {
                    System.out.println("JWT Token MalformedJwtException");
                }
            } else {
                //System.out.println("filter :requestTokenHeader is null || not start with bearer");
                //logger.warn("JWT Token does not begin with Bearer String");
            }
    
            // 验证,
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                //System.out.println("filter:username!=null");
                UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
                // JWT 验证通过 使用Spring Security 管理
                if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
                    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    //System.out.println("usernamePasswordAuthenticationToken:"+usernamePasswordAuthenticationToken.toString());
                    SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
                } else {
                   // System.out.println("jwtTokenUtil.validateToken not success");
                }
            }
            chain.doFilter(request, response);
        }
    }

    这个filter实现在针对jwt token的验证,把token转化成了相应的用户信息保存到了session中

    4,security/WebSecurityConfig.java

    @Configuration
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Resource
        private UserAuthenticationEntryPoint userAuthenticationEntryPoint;
    
        @Autowired
        private UserDetailsService jwtUserDetailsService;
    
        @Autowired
        private JwtRequestFilter jwtRequestFilter;
    
        @Resource
        private UserAccessDeniedHandler userAccessDeniedHandler;
    
        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            // configure AuthenticationManager so that it knows from where to load
            // user for matching credentials
            // Use BCryptPasswordEncoder
            auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
    
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception {
            // 本示例不需要使用CSRF
            httpSecurity.csrf().disable();
            httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            // 认证页面不需要权限
            httpSecurity.authorizeRequests().
                    antMatchers("/auth/authenticate").permitAll().
                    //其他页面
                    anyRequest().authenticated();
            //access deny
            httpSecurity.exceptionHandling().accessDeniedHandler(userAccessDeniedHandler);
            //unauthorized
            httpSecurity.exceptionHandling().authenticationEntryPoint(userAuthenticationEntryPoint);
            //验证请求是否正确
            httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        }
    }

    注意其中把jwt的过滤器添加到了HttpSecurity中

    5,其他代码请参见gitee

    四,查看spring boot的版本:

      .   ____          _            __ _ _
     /\ / ___'_ __ _ _(_)_ __  __ _    
    ( ( )\___ | '_ | '_| | '_ / _` |    
     \/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::                (v2.5.4)
  • 相关阅读:
    PTA 乙级 1032 挖掘机技术哪家强 (20分) C++
    Jmeter接口测试之MD5函数使用
    charles基础理论一
    Jmeter接口测试之函数和cookies
    appium+robotframework之权限设置
    appium+robotframework之context问题解决
    jmeter接口测试之断言持续时间
    Appium+robotframework 自动化之软键盘的调起(文本框无法输入值)
    Jmeter接口测试之测试计划和线程组的关系
    Jmeter接口测试之用户定义变量
  • 原文地址:https://www.cnblogs.com/architectforest/p/15185416.html
Copyright © 2011-2022 走看看