Java应用开发(中、高级)课件 任务2.3 实现API的Toen认证_第1页
Java应用开发(中、高级)课件 任务2.3 实现API的Toen认证_第2页
Java应用开发(中、高级)课件 任务2.3 实现API的Toen认证_第3页
Java应用开发(中、高级)课件 任务2.3 实现API的Toen认证_第4页
Java应用开发(中、高级)课件 任务2.3 实现API的Toen认证_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

任务三

实现API的Token认证03

任务描述本任务将通过SpringSecurity和JsonWebToken(JWT)完成接口的权限控制,即在未登录前无法访问受保护的接口,成功登录获取到token后,能够通过token访问受保护的接口。

知识准备1SpringSecurity框架SpringSecurity框架是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。SpringSecurity致力于为Java应用程序提供身份验证和授权。SpringBoot对于SpringSecurity提供了自动化配置方案,可以零配置使用SpringSecurity。

知识准备2数据库连接池数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;在项目中,一般情况下访问数据库,会创建一个连接,用完后就关闭它,对于简单的系统这样不会带来什么明显的性能上的开销。但是对于一个复杂的系统,频繁的建立、关闭连接,会极大的减低系统的性能,因为对于数据库连接的使用可能会成为系统性能的瓶颈。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。

任务实施步骤1:引入认证工具类t1在pom.xml文件中,引入MySQL驱动包、Mybatis框架、SpringSecurity框架以及JWT包,添加下面的代码:<!--mybatis--><dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.0.1</version></dependency><!--数据库驱动--><dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> <version>8.0.15</version></dependency><!--springsecurity安全认证--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><!--Token生成与解析--><dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.0</version></dependency>

任务实施步骤1:引入认证工具类t2选中perties文件,右键单击,依次选择“Refactor->Rename”打开重命名窗口,将perties文件重命名为application.yml文件,结果如图3-11所示:

任务实施步骤1:引入认证工具类t3)在application.yml文件中,添加下面的代码server:port:8080#指定打印日志配置logging:level:#定义项目mapper包下的日志打印机别为debugcom.chinasofti.ordersys.mapper:DEBUGspring:profiles:active:dev#热编译devtools:restart:#需要实时更新的目录additional-paths:resources/**,static/**,templates/**datasource:driver-class-name:com.mysql.cj.jdbc.Driverurl:jdbc:mysql://:3306/ordersys?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=UTCusername:rootpassword:rootplatform:mysql

任务实施步骤1:引入认证工具类t#连接池配置type:com.zaxxer.hikari.HikariDataSourcehikari:#连接池中允许的最小连接数。缺省值:10minimum-idle:10#连接池中允许的最大连接数。缺省值:10maximum-pool-size:100#自动提交auto-commit:true#一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟idle-timeout:30000#连接池名字pool-name:HikariCP#一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒max-lifetime:1800000#等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException,缺省:30秒connection-timeout:30000#数据库连接测试语句connection-test-query:SELECT1mybatis:#指定实体类存放的包路径type-aliases-package:com.chinasofti.ordersys.model#指定mapper.xml文件的位置为/mybatis-mappers/下的所有xml文件mapper-locations:classpath:/mybatis-mappers/*#转换到驼峰命名configuration:mapUnderscoreToCamelCase:true#token配置token:#令牌自定义标识header:Authorization#令牌秘钥#secret:abcdefghijklmnopqrstuvwxyzsecret:(OREDERSYS:)_$^11244^%$_(IS:)_@@++--(BAD:)_++++_.sds_(GUY:)#令牌有效期(默认30分钟)expireTime:60

任务实施步骤1:引入认证工具类t4在common包下引入认证工具类,下载教材提供的代码包并解压到本地目录,结果如图3-12所示:

任务实施步骤1:引入认证工具类t5将代码包中common文件夹下的代码,复制到项目目录common包下,结果如图3-13所示:

任务实施步骤1:引入认证工具类t

任务实施步骤1:引入认证工具类t6在util包下引入认证工具类,将代码包中util的代码,复制到项目目录util包下,结果如图3-14所示::

任务实施步骤1:引入认证工具类t

任务实施步骤2:编写权限认证配置类t1在项目目录config包下,右键config包,依次选择“New->Class”,创建SecuityConfig类文件,结果如图3-15所示:

任务实施步骤2:编写权限认证配置类t2SecurityConfig类需要继承WebSecurityConfigurerAdapter抽象类,重写configure(HttpSecurityhttp)方法,用来配置资源访问权限和验证用户权限信息,在SecurityConfig.java文件中添加下面的代码:/**springsecurity配置*/@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true)publicclassSecurityConfigextendsWebSecurityConfigurerAdapter{/**自定义用户认证逻辑*/@AutowiredprivateUserDetailsServiceuserDetailsService;/**认证失败处理类*/@AutowiredprivateAuthenticationEntryPointImplunauthorizedHandler;/**token认证过滤器*/@AutowiredprivateJwtAuthenticationTokenFilterauthenticationTokenFilter;/**解决

无法直接注入AuthenticationManager*@return*@throwsException*/@Bean@OverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{returnsuper.authenticationManagerBean();}

任务实施步骤2:编写权限认证配置类t/**强散列哈希加密实现*/@BeanpublicBCryptPasswordEncoderbCryptPasswordEncoder(){returnnewBCryptPasswordEncoder();}/**身份认证接口*/@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}}

任务实施步骤2:编写权限认证配置类t3编写SecurityConfig类,根据接口服务的项目特点,我们需要在认证服务中解决下面的问题:①默认情况下,接口的权限控制②允许登录接口,静态资源的匿名访问③JWT接入到Security框架为了解决上述的问题,下面重写configure(HttpSecurityhttp)方法,我们在SecurityConfig.java文件中添加下面的代码:

任务实施步骤2:编写权限认证配置类t@Overrideprotectedvoidconfigure(HttpSecurityhttpSecurity)throwsException{httpSecurity.csrf().disable()//CRSF禁用,因为不使用session//认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()//基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//过滤请求//对于登录login接口允许匿名访问,.antMatchers("/login","/api","/t").anonymous()//除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();//添加JWTfilterhttpSecurity.addFilterBefore(authenticationTokenFilter,UsernamePasswordAuthenticationFilter.class);}

任务实施步骤2:编写权限认证配置类t在上面的代码中,重点关注几个部分:

任务实施步骤2:编写权限认证配置类t4编写ConfigurerAdapter类,由于现代浏览器的请求策略,前后端服务使用的域名不一致的情况下,会导致接口访问异常;在本项目中,通过后台的跨域配置,解决此问题。在项目目录config包下,右键config包,依次选择“New”->“Class”,创建ConfigurerAdapter类文件,结果如图3-16所示:

任务实施步骤2:编写权限认证配置类t5在ConfigurerAdapter类文件中,编写下面的代码,启用服务器的跨域配置。@Configuration@EnableWebMvcpublicclassConfigurerAdapterimplementsWebMvcConfigurer{//令牌自定义标识@Value("${token.header}")privateStringheader;@BeanpublicCorsFiltercorsFilter(){UrlBasedCorsConfigurationSourcesource=newUrlBasedCorsConfigurationSource();CorsConfigurationconfig=newCorsConfiguration();config.setAllowCredentials(true);config.addAllowedOrigin("*");config.addAllowedHeader("*");config.addAllowedMethod("*");config.setExposedHeaders(Arrays.asList(header));source.registerCorsConfiguration("/**",config);returnnewCorsFilter(source);}}

任务实施步骤2:编写权限认证配置类t6编写GlobalExceptionHandler类用于全局错误处理,在项目目录config包下,右键config包,依次选择“New”->“Class”,创建GlobalExceptionHandler类文件,结果如图3-17所示:

任务实施步骤2:编写权限认证配置类t7GlobalExceptionHandler中编写下面的代码,通过下面的配置,将应用运行时异常全部拦截,并统一进行处理,返回自定义的业务返回码。@RestControllerAdvicepublicclassGlobalExceptionHandler{/***拦截所有运行时的全局异常

*/@ExceptionHandler(RuntimeException.class)@ResponseBodypublicResultsruntimeException(RuntimeExceptione){returnResults.failure(ResponseCode.FAIL.getCode(),e.getMessage());}}

任务实施步骤3:新建用户登录接口t1.新建用户实体类(1)在model包下,右键model包,依次选择“New->Class”,新建UserInfo类,结果如图3-18所示:

任务实施步骤3:新建用户登录接口t(2)在UserInfo类中添加下面的代码publicclassUserInfo{ privateintuserId;//用户ID privateStringuserAccount;//用户账户 privateStringuserPass;//用户密码 privateintroleId;//用户角色ID privateStringroleName;//用户角色名 privateintlocked;//用户是否被锁定的标识 privateStringfaceimg="default.jpg";//用户头像路径 publicStringgetFaceimg(){ returnfaceimg; } publicvoidsetFaceimg(Stringfaceimg){ this.faceimg=faceimg; } publicintgetLocked(){ returnlocked; } publicvoidsetLocked(intlocked){ this.locked=locked; } publicintgetUserId(){ returnuserId; } publicvoidsetUserId(intuserId){ this.userId=userId; }

任务实施步骤3:新建用户登录接口t publicStringgetUserAccount(){ returnuserAccount; } publicvoidsetUserAccount(StringuserAccount){ this.userAccount=userAccount; } publicStringgetUserPass(){ returnuserPass; } publicvoidsetUserPass(StringuserPass){ this.userPass=userPass; } publicintgetRoleId(){ returnroleId; } publicvoidsetRoleId(introleId){ this.roleId=roleId; } publicStringgetRoleName(){ returnroleName; } publicvoidsetRoleName(StringroleName){ this.roleName=roleName; }}

任务实施步骤3:新建用户登录接口t2.新建登录Mapper接口(1)在mapper包下新建LoginMapper类,结果如图3-19所示:

任务实施步骤3:新建用户登录接口t(2)在LoginMapper类中添加下面的代码。@MapperpublicinterfaceLoginMapper{ @Select("selectuserId,userAccount,userPass,locked,roleId,roleName,faceimgfromuserinfo,roleinfowhereuserinfo.role=roleinfo.roleIdanduserinfo.userAccount=#{userAccount}") publicList<UserInfo>findUsersByName(@Param("userAccount")StringuserAccount);}

任务实施步骤3:新建用户登录接口t3.新建登录Service类(1)在service包下,右键service包,依次选择“New”->“Package”,新建login包结果如图3-20所示:

任务实施步骤3:新建用户登录接口t(2)在service.login包下新建LoginService类,结果如图3-21所示::

任务实施步骤3:新建用户登录接口t(3)在LoginService类中添加下面的代码@ServicepublicclassLoginService{ @AutowiredLoginMappermapper; publicLoginMappergetMapper(){ returnmapper; } publicvoidsetMapper(LoginMappermapper){ this.mapper=mapper; } /**

*根据用户名查询用户数据 *@paramuserAccount *@return */ publicUserInfofindUserByName(StringuserAccount){ List<UserInfo>list=mapper.findUsersByName(userAccount); UserInfouserInfo=null; if(null!=list&&list.size()==1){ userInfo=list.get(0); } returnuserInfo; }}

任务实施步骤3:新建用户登录接口t4.新建登录Api接口(1)在api包下新建login包,结果如图3-22所示:

任务实施步骤3:新建用户登录接口t

(2)在api.login包下新建LoginController类,结果如图3-23所示

任务实施步骤3:新建用户登录接口t

(3)在LoginController类中,新增登录逻辑,添加下面的代码:@RestControllerpublicclassLoginController{ @AutowiredLoginServiceloginService; @AutowiredSysLoginServicesysLoginService; /**

*登录方法

*@paramusername用户名

*@parampassword密码

*@return结果 */ @PostMapping("/login") publicResultslogin(Stringusername,Stringpassword){ System.out.println("/login:username["+username+"]"+"password:["+password+"]");

//生成令牌 Stringtoken=sysLoginService.login(username,password); LoginUseruser=UserHandleUtils.getUser(token); UserInfouserInfo=user.getUser(); userInfo.setUserPass(""); Map<String,Object>res=newHashMap<>(3); res.put("token",token); res.put("user",userInfo); returnResults.success(res); }}

任务实施步骤3:新建用户登录接口t5.添加两个用于测试登陆结果的接口,添加下面的代码:@GetMapping({"/auth"}) publicResultsauth(Stringusername){ System.out.println("/auth:username["+username+"]"); //生成令牌 Map<String,Object>res=newHashMap<>(); res.put("api","auth"); res.put("username",username); res.put("msg","登录后可见"); returnResults.success(res); }

@PreAuthorize("hasRole('3')") @GetMapping({"/waiter"}) publicResultstestRoleWaiter(Stringusername){ System.out.println("/test:username["+userna

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论