1.项目创建


1、新建工程




2、选择打包方式,这边可以选择为打包为Jar包,或者传统的打包为War包



3、选择开发过程中使用到的技术,这边我选择的是Rest Repositories



4、新建测试用Controller



    文件内容如下

[java]  view plain  copy
  1. package com.xiaofangtech.example;  
  2.   
  3. import org.springframework.web.bind.annotation.RequestMapping;  
  4. import org.springframework.web.bind.annotation.RestController;  
  5.   
  6. @RestController  
  7. public class HelloController {  
  8.     @RequestMapping("/greeting")  
  9.     public String hello()  
  10.     {  
  11.         return "Hello world";  
  12.     }  
  13. }  

5、以Srping Boot App 方式运行



正常运行后控制台如下



6、测试运行


至此,一个最简单的hello world的工程创建运行完成


7、打包部署

   7.1 打包为可运行jar包

   使用mvn package 进行打包

   



 然后run ,运行成功后如下生成jar包






 7.2 打包为传统的war包 

       当第2步中选择的打包方式为war时,执行7.1中mvn package时,生成的包就是war包

     



运行war包跟运行jar包一样,找到war包所在目录,注解运行war包


D:\new_tech\spring-suite-tool\workspace\workspace1\demo1\target>java -jar demo1-0.0.1-SNAPSHOT.war


访问服务接口: localhost:8080/greeting



2.代码实现连接数据实现Rest接口和Basic 基础认证

0.引入pom依赖

<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!-- 使用MySQL数据库,并用Spring Data JPA来作为数据库访问 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>




1.代码整体结构



2.注册Filter过滤器的两种方式:
        1.在自定义的Filter上使用注解:
           
/*
 * Filter实现简单的Http Basic 认证 
 */
@Component
@WebFilter(filterName = "httpBasicAuthorizedFilter", urlPatterns="/user/*")
public class HttpBasicAuthorizeFilter implements Filter {

       2.在配置类中定义Filter

@Bean  
    public FilterRegistrationBean  filterRegistrationBean() {  
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();  
        HttpBasicAuthorizeFilter httpBasicFilter = new HttpBasicAuthorizeFilter();  
        registrationBean.setFilter(httpBasicFilter);  
        List<String> urlPatterns = new ArrayList<String>();  
        urlPatterns.add("/user/*");  
        registrationBean.setUrlPatterns(urlPatterns);  
        return registrationBean;  
    }  


3.数据库和Rest接口操作效果展示:



4.过滤器效果展示
  
代码中固定用户名密码都为test,所以对接口进行请求时,需要添加以下认证头信息

Authorization: Basic dGVzdDp0ZXN0

dGVzdDp0ZXN0 为 test:test 经过base64编码后的结果


如果未添加认证信息或者认证信息错误,返回没有权限的错误信息




当认证信息正确,返回请求结果



    3.自定义Properties解析类和分布式Token JWT用户校验

        1.自定义Properties解析类的使用规则

                      1.定义Properties配置文件   ---- jwt.properties
                          
    jwt.info.clientId=098f6bcd4621d373cade4e832627b4f6
    jwt.info.base64Secret=MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=
    jwt.info.name=restapiuser
    jwt.info.expiresSecond=172800


                      2.自定义解析类                      ---- JwtInfo.java  指定配置文件地址和配置前缀,属性是前缀之后的名称
    package com.jay.properties;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    /*
     * 自定义配置文件的解析类
     */
    @ConfigurationProperties(prefix = "jwt.info", locations = "classpath:/config/jwt.properties")
    public class JwtInfo {
    	private String clientId;  
        private String base64Secret;  
        private String name;  
        private int expiresSecond;
    	public String getClientId() {
    		return clientId;
    	}
    	public void setClientId(String clientId) {
    		this.clientId = clientId;
    	}
    	public String getBase64Secret() {
    		return base64Secret;
    	}
    	public void setBase64Secret(String base64Secret) {
    		this.base64Secret = base64Secret;
    	}
    	public String getName() {
    		return name;
    	}
    	public void setName(String name) {
    		this.name = name;
    	}
    	public int getExpiresSecond() {
    		return expiresSecond;
    	}
    	public void setExpiresSecond(int expiresSecond) {
    		this.expiresSecond = expiresSecond;
    	}
    	
    }
    



                      3.启动类或配置类中,指定自定义Properties解析类
    package com.jay;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties.Jwt;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    
    import com.jay.properties.JwtInfo;
    
    @SpringBootApplication
    @EnableConfigurationProperties(JwtInfo.class)  //加载自定义的properties解析类
    public class Demo1Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Demo1Application.class, args);
    	}
    }
    

                   4.输出配置文件信息         ---- JwtInfoController.java

    package com.jay.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.jay.properties.JwtInfo;
    import com.jay.vo.ResultMsg;
    import com.jay.vo.ResultStatusCode;
    
    @RestController
    @RequestMapping("/jwt")
    public class JwtInfoController {
    
    	@Autowired
    	private JwtInfo jwtInfo;
    
    	@RequestMapping(value = "/info", method = RequestMethod.GET)
    	public Object getJwtInfo() {
    		return new ResultMsg<JwtInfo>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), jwtInfo);
    	}
    }
    

                   5.效果展示
                  


              2.使用分布式token  JWT进行用户认证


                  

    jwt(json web token)

    用户发送按照约定,向服务端发送 Header、Payload 和 Signature,并包含认证信息(密码),验证通过后服务端返回一个token,之后用户使用该token作为登录凭证,适合于移动端和api


    jwt使用流程



                  1.添加 JWT依赖
    <!-- JWT Json Web Token 依赖 -->
    		<dependency>
    		    <groupId>io.jsonwebtoken</groupId>
    		    <artifactId>jjwt</artifactId>
    		    <version>0.7.0</version>
    		</dependency>

                 2.编写Jwt解析类和Jwt过滤器
                 
    package com.jay.util.jwt;
    
    import java.security.Key;
    import java.util.Date;
    
    import javax.crypto.spec.SecretKeySpec;
    import javax.xml.bind.DatatypeConverter;
    
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.JwtBuilder;
    import io.jsonwebtoken.Jwts;
    import io.jsonwebtoken.SignatureAlgorithm;
    
    /*
     * 构造及解析jwt的工具类
     */
    public class JwtHelper {
    	public static Claims parseJWT(String jsonWebToken, String base64Security){
    		try
    		{
    			Claims claims = Jwts.parser()
    					   .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
    					   .parseClaimsJws(jsonWebToken).getBody();
    			return claims;
    		}
    		catch(Exception ex)
    		{
    			return null;
    		}
    	}
    	
    	/**
    	 * 生成token
    	 * 
    	 * @author hetiewei
    	 * @date 2016年10月18日 下午2:51:38
    	 * @param name     keyId
    	 * @param userId   
    	 * @param role
    	 * @param audience   接收者
    	 * @param issuer     发行者
    	 * @param TTLMillis  过期时间(毫秒)
    	 * @param base64Security
    	 * @return
    	 */
    	public static String createJWT(String name, String userId, String role, 
    			String audience, String issuer, long TTLMillis, String base64Security) 
    	{
    		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
    		 
    		long nowMillis = System.currentTimeMillis();
    		Date now = new Date(nowMillis);
    		 
    		//生成签名密钥
    		byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
    		Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
    		 
    		  //添加构成JWT的参数
    		JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
    										.claim("role", role)
    				                        .claim("unique_name", name)
    				                        .claim("userid", userId)
    				                        .setIssuer(issuer)
    				                        .setAudience(audience)
    		                                .signWith(signatureAlgorithm, signingKey);
    		 //添加Token过期时间
    		if (TTLMillis >= 0) {
    		    long expMillis = nowMillis + TTLMillis;
    		    Date exp = new Date(expMillis);
    		    builder.setExpiration(exp).setNotBefore(now);
    		}
    		 
    		 //生成JWT
    		return builder.compact();
    	} 
    }
    




    package com.jay.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.context.support.SpringBeanAutowiringSupport;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.jay.properties.JwtInfo;
    import com.jay.util.jwt.JwtHelper;
    import com.jay.vo.ResultMsg;
    import com.jay.vo.ResultStatusCode;
    
    /*
     * 用于JWT认证的过滤器
     */
    public class JwtAuthorizeFilter implements Filter{
    	
    	/*
    	 * 注入配置文件类
    	 */
    	@Autowired
    	private JwtInfo jwtInfo;
    
    	@Override
    	public void destroy() {
    		
    	}
    
    	@Override
    	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    			throws IOException, ServletException {
    		 ResultMsg<Object> resultMsg;  
    	        HttpServletRequest httpRequest = (HttpServletRequest)request;  
    	        String auth = httpRequest.getHeader("Authorization");  
    	        if ((auth != null) && (auth.length() > 7))  
    	        {  
    	            String HeadStr = auth.substring(0, 6).toLowerCase();  
    	            if (HeadStr.compareTo("bearer") == 0)  
    	            {  
    	                  
    	                auth = auth.substring(7, auth.length());   
    	                if (JwtHelper.parseJWT(auth, jwtInfo.getBase64Secret()) != null)  
    	                {  
    	                    chain.doFilter(request, response);  
    	                    return;  
    	                }  
    	            }  
    	        }  
    	        
    	        //验证不通过
    	        HttpServletResponse httpResponse = (HttpServletResponse) response;  
    	        httpResponse.setCharacterEncoding("UTF-8");    
    	        httpResponse.setContentType("application/json; charset=utf-8");   
    	        httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);  
    	  
    	        //将验证不通过的错误返回
    	        ObjectMapper mapper = new ObjectMapper();  
    	          
    	        resultMsg = new ResultMsg<Object>(true, ResultStatusCode.INVALID_TOKEN.getErrorCode(), ResultStatusCode.INVALID_TOKEN.getErrorMsg(), null);  
    	        httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));  
    	        return;  
    	}
    
    	@Override
    	public void init(FilterConfig filterConfig) throws ServletException {
    		SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, filterConfig.getServletContext());
    	}
    
    }
    







                3.在Jwt配置类中,添加过滤器
                 
    package com.jay.config;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.boot.context.embedded.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import com.jay.filter.JwtAuthorizeFilter;
    
    
    /*
     * 注册jwt认证过滤器
     */
    @Configuration
    public class JwtConfig {
    	
    	/*
    	 * 注册过滤器类和过滤的url
    	 */
    	@Bean
    	public FilterRegistrationBean basicFilterRegistrationBean(){
    		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    		JwtAuthorizeFilter filter = new JwtAuthorizeFilter();
    		registrationBean.setFilter(filter);
    		
    		List<String> urlPatterns = new ArrayList<>();
    		urlPatterns.add("/user/*");
    		
    		registrationBean.setUrlPatterns(urlPatterns);
    		return registrationBean;
    	}
    }
    

     
                
                4.效果展示:
                           1.  获取token,传入用户认证信息





                        2. 使用上面获取的token进行接口调用,      未使用token,获取token错误,或者token过期时



                   3.使用正确的token时
                       

                        



    特别注意:
                  JWT使用时,可以通过Cookie机制,自动的传递!!!


    4.Redis + Cookie 机制,进行验证码的校验


    1.添加redis和captcha库依赖

    <!-- 整合redis -->
    		 <dependency>  
    		    <groupId>org.springframework.boot</groupId>  
    		    <artifactId>spring-boot-starter-redis</artifactId>  
    		</dependency>  
    		<!-- 第三方验证码库 -->
    		<dependency>
    		    <groupId>cn.apiclub.tool</groupId>
    		    <artifactId>simplecaptcha</artifactId>
    		    <version>1.2.2</version>
    		</dependency>


    2.redis配置

    ##Redis配置
    spring.redis.database=1
    spring.redis.host=localhost
    #spring.redis.password=password
    spring.redis.port=6379
    spring.redis.timeout=2000
    spring.redis.pool.max-idle=8
    spring.redis.pool.min-idle=0
    spring.redis.pool.max-active=8
    spring.redis.pool.max-wait=-1


    3.Redis配置类,实例化Redis模板

    package com.jay.config;
    
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.data.redis.connection.RedisConnectionFactory;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.StringRedisTemplate;
    import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
    
    import com.fasterxml.jackson.annotation.JsonAutoDetect;
    import com.fasterxml.jackson.annotation.PropertyAccessor;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    @Configuration
    public class RedisConfig {
    	
    	// 定义Redis模板
    	@Bean
    	public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
    		StringRedisTemplate template = new StringRedisTemplate(factory);
    		// 设置序列化工具, 这样缓存的Bean就不需要再试下Serializable接口
    		setSerrializer(template);
    		template.afterPropertiesSet();
    		return template;
    	}
    
    	// 设置序列化
    	private void setSerrializer(StringRedisTemplate template) {
    		Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    		ObjectMapper om = new ObjectMapper();
    		om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    		om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    		jackson2JsonRedisSerializer.setObjectMapper(om);
    		template.setValueSerializer(jackson2JsonRedisSerializer);
    	}
    }
    


    4.Controller层操作代码

    package com.jay.controller;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.UUID;
    import java.util.concurrent.TimeUnit;
    
    import javax.imageio.ImageIO;
    import javax.servlet.http.Cookie;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.http.HttpRequest;
    import org.springframework.http.MediaType;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.jay.util.CookieUtils;
    import com.jay.vo.ResultMsg;
    import com.jay.vo.ResultStatusCode;
    
    import cn.apiclub.captcha.Captcha;
    import cn.apiclub.captcha.backgrounds.GradiatedBackgroundProducer;
    import cn.apiclub.captcha.gimpy.FishEyeGimpyRenderer;
    import io.swagger.annotations.ApiOperation;
    
    @Controller
    @RequestMapping("/redis")
    public class RedisCaptchaController {
    
    	@Autowired
    	private RedisTemplate<String, String> redisTemplate;
    
    	private static int captchaExpires = 3 * 60; // 超时时间3min,验证码超时,自动冲redis中删除
    	private static int captchaW = 200;
    	private static int captchaH = 60;
    	private static String cookieName = "CaptchaCode";
    
    	@RequestMapping(value = "getcaptcha", method = RequestMethod.GET, produces = MediaType.IMAGE_PNG_VALUE)
    	public @ResponseBody byte[] getCaptcha(HttpServletResponse response) {
    		// 生成验证码
    		String uuid = UUID.randomUUID().toString();
    		Captcha captcha = new Captcha.Builder(captchaW, captchaH).addText()
    				.addBackground(new GradiatedBackgroundProducer()).gimp(new FishEyeGimpyRenderer()).build();
    
    		// 将验证码以<key,value>形式缓存到redis
    		redisTemplate.opsForValue().set(uuid, captcha.getAnswer(), captchaExpires, TimeUnit.SECONDS);
    
    		// 将验证码key,及验证码的图片返回
    		Cookie cookie = new Cookie(cookieName, uuid);
    		response.addCookie(cookie);
    		ByteArrayOutputStream bao = new ByteArrayOutputStream();
    		try {
    			ImageIO.write(captcha.getImage(), "png", bao);
    			return bao.toByteArray();
    		} catch (IOException e) {
    			return null;
    		}
    	}
    	
    	/*
    	 * 说明:
    	 *    1.captchaCode来自客户端的Cookie,在访问时,通过服务端设置
    	 *    2.captcha是用户填写的验证码,将用户填写的验证码和通过captchaCode从redis中获取的验证码进行对比即可
    	 * 
    	 */
    	@ApiOperation(value = "验证码校验")
    	@RequestMapping(value = "/captcha/check/{captcha}")
    	@ResponseBody
    	public ResultMsg<Object> checkCaptcha(@PathVariable("captcha") String captcha, HttpServletRequest request){
    		
    		String captchaCode = CookieUtils.getCookie(request, cookieName);
    		
    		ResultMsg<Object> result;
    		
    		try{
    		if (captcha == null)  
    	    {  
    	        throw new Exception();  
    	    }  
    		
    		//redis中查询验证码
    		String captchaValue = redisTemplate.opsForValue().get(captchaCode);
    		
    		if (captchaValue == null) {
    			throw new Exception();
    		}
    		
    		if (captchaValue.compareToIgnoreCase(captcha) != 0) {
    			throw new Exception();
    		}
    		
    		//验证码匹配成功,redis则删除对应的验证码
    	    redisTemplate.delete(captchaCode);
    				
    		return new ResultMsg<Object>(true, ResultStatusCode.OK.getErrorCode(), ResultStatusCode.OK.getErrorMsg(), null);
    
    		}catch (Exception e) {
    			result = new ResultMsg<Object>(false, ResultStatusCode.INVALID_CAPTCHA.getErrorCode(), ResultStatusCode.INVALID_CAPTCHA.getErrorMsg(), null);
    		}
    		return result;
    	}
    	
    
    }
    


    5.效果展示

    1.访问生成验证码



    2.验证验证码



    项目源码下载: 下载地址




    Logo

    讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

    更多推荐