查看原文
其他

mall整合SpringSecurity和JWT实现认证和授权(二)

梦想de星空 macrozheng 2020-08-20
来自专辑
mall学习教程(架构篇)

接上一篇,controller和service层的代码实现及登录授权流程演示。

登录注册功能实现

添加UmsAdminController类

实现了后台用户登录、注册及获取权限的接口

  1. package com.macro.mall.tiny.controller;


  2. import com.macro.mall.tiny.common.api.CommonResult;

  3. import com.macro.mall.tiny.dto.UmsAdminLoginParam;

  4. import com.macro.mall.tiny.mbg.model.UmsAdmin;

  5. import com.macro.mall.tiny.mbg.model.UmsPermission;

  6. import com.macro.mall.tiny.service.UmsAdminService;

  7. import io.swagger.annotations.Api;

  8. import io.swagger.annotations.ApiOperation;

  9. import org.springframework.beans.factory.annotation.Autowired;

  10. import org.springframework.beans.factory.annotation.Value;

  11. import org.springframework.stereotype.Controller;

  12. import org.springframework.validation.BindingResult;

  13. import org.springframework.web.bind.annotation.*;


  14. import java.util.HashMap;

  15. import java.util.List;

  16. import java.util.Map;


  17. /**

  18. * 后台用户管理

  19. * Created by macro on 2018/4/26.

  20. */

  21. @Controller

  22. @Api(tags = "UmsAdminController", description = "后台用户管理")

  23. @RequestMapping("/admin")

  24. public class UmsAdminController {

  25. @Autowired

  26. private UmsAdminService adminService;

  27. @Value("${jwt.tokenHeader}")

  28. private String tokenHeader;

  29. @Value("${jwt.tokenHead}")

  30. private String tokenHead;


  31. @ApiOperation(value = "用户注册")

  32. @RequestMapping(value = "/register", method = RequestMethod.POST)

  33. @ResponseBody

  34. public CommonResult<UmsAdmin> register(@RequestBody UmsAdmin umsAdminParam, BindingResult result) {

  35. UmsAdmin umsAdmin = adminService.register(umsAdminParam);

  36. if (umsAdmin == null) {

  37. CommonResult.failed();

  38. }

  39. return CommonResult.success(umsAdmin);

  40. }


  41. @ApiOperation(value = "登录以后返回token")

  42. @RequestMapping(value = "/login", method = RequestMethod.POST)

  43. @ResponseBody

  44. public CommonResult login(@RequestBody UmsAdminLoginParam umsAdminLoginParam, BindingResult result) {

  45. String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword());

  46. if (token == null) {

  47. return CommonResult.validateFailed("用户名或密码错误");

  48. }

  49. Map<String, String> tokenMap = new HashMap<>();

  50. tokenMap.put("token", token);

  51. tokenMap.put("tokenHead", tokenHead);

  52. return CommonResult.success(tokenMap);

  53. }


  54. @ApiOperation("获取用户所有权限(包括+-权限)")

  55. @RequestMapping(value = "/permission/{adminId}", method = RequestMethod.GET)

  56. @ResponseBody

  57. public CommonResult<List<UmsPermission>> getPermissionList(@PathVariable Long adminId) {

  58. List<UmsPermission> permissionList = adminService.getPermissionList(adminId);

  59. return CommonResult.success(permissionList);

  60. }

  61. }

添加UmsAdminService接口

  1. package com.macro.mall.tiny.service;


  2. import com.macro.mall.tiny.mbg.model.UmsAdmin;

  3. import com.macro.mall.tiny.mbg.model.UmsPermission;


  4. import java.util.List;


  5. /**

  6. * 后台管理员Service

  7. * Created by macro on 2018/4/26.

  8. */

  9. public interface UmsAdminService {

  10. /**

  11. * 根据用户名获取后台管理员

  12. */

  13. UmsAdmin getAdminByUsername(String username);


  14. /**

  15. * 注册功能

  16. */

  17. UmsAdmin register(UmsAdmin umsAdminParam);


  18. /**

  19. * 登录功能

  20. * @param username 用户名

  21. * @param password 密码

  22. * @return 生成的JWT的token

  23. */

  24. String login(String username, String password);


  25. /**

  26. * 获取用户所有权限(包括角色权限和+-权限)

  27. */

  28. List<UmsPermission> getPermissionList(Long adminId);

  29. }

添加UmsAdminServiceImpl类

  1. package com.macro.mall.tiny.service.impl;


  2. import com.macro.mall.tiny.common.utils.JwtTokenUtil;

  3. import com.macro.mall.tiny.dao.UmsAdminRoleRelationDao;

  4. import com.macro.mall.tiny.dto.UmsAdminLoginParam;

  5. import com.macro.mall.tiny.mbg.mapper.UmsAdminMapper;

  6. import com.macro.mall.tiny.mbg.model.UmsAdmin;

  7. import com.macro.mall.tiny.mbg.model.UmsAdminExample;

  8. import com.macro.mall.tiny.mbg.model.UmsPermission;

  9. import com.macro.mall.tiny.service.UmsAdminService;

  10. import org.slf4j.Logger;

  11. import org.slf4j.LoggerFactory;

  12. import org.springframework.beans.BeanUtils;

  13. import org.springframework.beans.factory.annotation.Autowired;

  14. import org.springframework.beans.factory.annotation.Value;

  15. import org.springframework.security.authentication.AuthenticationManager;

  16. import org.springframework.security.authentication.BadCredentialsException;

  17. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

  18. import org.springframework.security.core.AuthenticationException;

  19. import org.springframework.security.core.context.SecurityContextHolder;

  20. import org.springframework.security.core.userdetails.UserDetails;

  21. import org.springframework.security.core.userdetails.UserDetailsService;

  22. import org.springframework.security.crypto.password.PasswordEncoder;

  23. import org.springframework.stereotype.Service;


  24. import java.util.Date;

  25. import java.util.List;


  26. /**

  27. * UmsAdminService实现类

  28. * Created by macro on 2018/4/26.

  29. */

  30. @Service

  31. public class UmsAdminServiceImpl implements UmsAdminService {

  32. private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class);

  33. @Autowired

  34. private UserDetailsService userDetailsService;

  35. @Autowired

  36. private JwtTokenUtil jwtTokenUtil;

  37. @Autowired

  38. private PasswordEncoder passwordEncoder;

  39. @Value("${jwt.tokenHead}")

  40. private String tokenHead;

  41. @Autowired

  42. private UmsAdminMapper adminMapper;

  43. @Autowired

  44. private UmsAdminRoleRelationDao adminRoleRelationDao;


  45. @Override

  46. public UmsAdmin getAdminByUsername(String username) {

  47. UmsAdminExample example = new UmsAdminExample();

  48. example.createCriteria().andUsernameEqualTo(username);

  49. List<UmsAdmin> adminList = adminMapper.selectByExample(example);

  50. if (adminList != null && adminList.size() > 0) {

  51. return adminList.get(0);

  52. }

  53. return null;

  54. }


  55. @Override

  56. public UmsAdmin register(UmsAdmin umsAdminParam) {

  57. UmsAdmin umsAdmin = new UmsAdmin();

  58. BeanUtils.copyProperties(umsAdminParam, umsAdmin);

  59. umsAdmin.setCreateTime(new Date());

  60. umsAdmin.setStatus(1);

  61. //查询是否有相同用户名的用户

  62. UmsAdminExample example = new UmsAdminExample();

  63. example.createCriteria().andUsernameEqualTo(umsAdmin.getUsername());

  64. List<UmsAdmin> umsAdminList = adminMapper.selectByExample(example);

  65. if (umsAdminList.size() > 0) {

  66. return null;

  67. }

  68. //将密码进行加密操作

  69. String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());

  70. umsAdmin.setPassword(encodePassword);

  71. adminMapper.insert(umsAdmin);

  72. return umsAdmin;

  73. }


  74. @Override

  75. public String login(String username, String password) {

  76. String token = null;

  77. try {

  78. UserDetails userDetails = userDetailsService.loadUserByUsername(username);

  79. if (!passwordEncoder.matches(password, userDetails.getPassword())) {

  80. throw new BadCredentialsException("密码不正确");

  81. }

  82. UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

  83. SecurityContextHolder.getContext().setAuthentication(authentication);

  84. token = jwtTokenUtil.generateToken(userDetails);

  85. } catch (AuthenticationException e) {

  86. LOGGER.warn("登录异常:{}", e.getMessage());

  87. }

  88. return token;

  89. }



  90. @Override

  91. public List<UmsPermission> getPermissionList(Long adminId) {

  92. return adminRoleRelationDao.getPermissionList(adminId);

  93. }

  94. }

修改Swagger的配置

通过修改配置实现调用接口自带Authorization头,这样就可以访问需要登录的接口了。

  1. package com.macro.mall.tiny.config;


  2. import org.springframework.context.annotation.Bean;

  3. import org.springframework.context.annotation.Configuration;

  4. import springfox.documentation.builders.ApiInfoBuilder;

  5. import springfox.documentation.builders.PathSelectors;

  6. import springfox.documentation.builders.RequestHandlerSelectors;

  7. import springfox.documentation.service.ApiInfo;

  8. import springfox.documentation.service.ApiKey;

  9. import springfox.documentation.service.AuthorizationScope;

  10. import springfox.documentation.service.SecurityReference;

  11. import springfox.documentation.spi.DocumentationType;

  12. import springfox.documentation.spi.service.contexts.SecurityContext;

  13. import springfox.documentation.spring.web.plugins.Docket;

  14. import springfox.documentation.swagger2.annotations.EnableSwagger2;


  15. import java.util.ArrayList;

  16. import java.util.List;


  17. /**

  18. * Swagger2API文档的配置

  19. */

  20. @Configuration

  21. @EnableSwagger2

  22. public class Swagger2Config {

  23. @Bean

  24. public Docket createRestApi(){

  25. return new Docket(DocumentationType.SWAGGER_2)

  26. .apiInfo(apiInfo())

  27. .select()

  28. //为当前包下controller生成API文档

  29. .apis(RequestHandlerSelectors.basePackage("com.macro.mall.tiny.controller"))

  30. .paths(PathSelectors.any())

  31. .build()

  32. //添加登录认证

  33. .securitySchemes(securitySchemes())

  34. .securityContexts(securityContexts());

  35. }


  36. private ApiInfo apiInfo() {

  37. return new ApiInfoBuilder()

  38. .title("SwaggerUI演示")

  39. .description("mall-tiny")

  40. .contact("macro")

  41. .version("1.0")

  42. .build();

  43. }


  44. private List<ApiKey> securitySchemes() {

  45. //设置请求头信息

  46. List<ApiKey> result = new ArrayList<>();

  47. ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");

  48. result.add(apiKey);

  49. return result;

  50. }


  51. private List<SecurityContext> securityContexts() {

  52. //设置需要登录认证的路径

  53. List<SecurityContext> result = new ArrayList<>();

  54. result.add(getContextByPath("/brand/.*"));

  55. return result;

  56. }


  57. private SecurityContext getContextByPath(String pathRegex){

  58. return SecurityContext.builder()

  59. .securityReferences(defaultAuth())

  60. .forPaths(PathSelectors.regex(pathRegex))

  61. .build();

  62. }


  63. private List<SecurityReference> defaultAuth() {

  64. List<SecurityReference> result = new ArrayList<>();

  65. AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");

  66. AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];

  67. authorizationScopes[0] = authorizationScope;

  68. result.add(new SecurityReference("Authorization", authorizationScopes));

  69. return result;

  70. }

  71. }

给PmsBrandController接口中的方法添加访问权限

  • 给查询接口添加pms:brand:read权限

  • 给修改接口添加pms:brand:update权限

  • 给删除接口添加pms:brand:delete权限

  • 给添加接口添加pms:brand:create权限

例子:

  1. @PreAuthorize("hasAuthority('pms:brand:read')")

  2. public CommonResult<List<PmsBrand>> getBrandList() {

  3. return CommonResult.success(brandService.listAllBrand());

  4. }

认证与授权流程演示

运行项目,访问API

Swagger api地址:http://localhost:8080/swagger-ui.html

未登录前访问接口

登录后访问接口

  • 进行登录操作:登录帐号test 123456

  • 点击Authorize按钮,在弹框中输入登录接口中获取到的token信息

  • 登录后访问获取权限列表接口,发现已经可以正常访问

访问需要权限的接口

由于test帐号并没有设置任何权限,所以他无法访问具有pms:brand:read权限的获取品牌列表接口。

改用其他有权限的帐号登录

改用admin 123456登录后访问,点击Authorize按钮打开弹框,点击logout登出后再重新输入新token。

项目源码地址

https://github.com/macrozheng/mall-learning/tree/master/mall-tiny-04

推荐阅读


    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存