<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot + Shiro + Mybatis-plus + Kaptcha + vue實(shí)現(xiàn)權(quán)限管理登錄功能

          共 55475字,需瀏覽 111分鐘

           ·

          2021-05-20 23:04

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          76套java從入門(mén)到精通實(shí)戰(zhàn)課程分享

          登錄功能

          使用到的技術(shù)

          • shiro

          • Mybatis-plus

          • Springboot

          • kaptcha

          參考優(yōu)秀博文

          一個(gè)博主做的shiro筆記:https://www.guitu18.com/post/2019/07/26/43.html

          引入依賴(lài)

           <dependencies>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-web</artifactId>
                  </dependency>

                  <dependency>
                      <groupId>mysql</groupId>
                      <artifactId>mysql-connector-java</artifactId>
                      <scope>runtime</scope>
                  </dependency>
                  <dependency>
                      <groupId>org.projectlombok</groupId>
                      <artifactId>lombok</artifactId>
                      <optional>true</optional>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-test</artifactId>
                      <scope>test</scope>
                  </dependency>

                  <!-- shiro -->
                  <dependency>
                      <groupId>org.apache.shiro</groupId>
                      <artifactId>shiro-spring</artifactId>
                      <version>1.7.0</version>
                  </dependency>

                  <!--mybatis-plus 持久層-->
                  <dependency>
                      <groupId>com.baomidou</groupId>
                      <artifactId>mybatis-plus-boot-starter</artifactId>
                      <version>3.4.1</version>
                  </dependency>

                  <!--   整合swagger     -->
                  <dependency>
                      <groupId>io.springfox</groupId>
                      <artifactId>springfox-swagger2</artifactId>
                      <version>2.8.0</version>
                  </dependency>
                  <dependency>
                      <groupId>io.springfox</groupId>
                      <artifactId>springfox-swagger-ui</artifactId>
                      <version>2.8.0</version>
                  </dependency>
                  <!-- kaptcha 驗(yàn)證碼 -->
                  <dependency>
                      <groupId>com.github.penggle</groupId>
                      <artifactId>kaptcha</artifactId>
                      <version>2.3.2</version>
                  </dependency>
              </dependencies>

          配置shiro

          package com.unclebb.zlgl.config;

          import com.unclebb.zlgl.utils.CustomRealm;
          import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
          import org.apache.shiro.mgt.DefaultSecurityManager;
          import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
          import org.apache.shiro.util.ThreadContext;
          import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
          import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
          import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;

          import java.util.HashMap;
          import java.util.Map;

          /**
           * @program: zlgl
           * @description: Shiro配置類(lèi):將SecurityManager以及Realm都注入到Spring容器中
           * @author: LiuZhiliang
           * @create: 2021-05-10 08:56
           **/
          @Configuration
          public class ShiroConfig {
           
           /** 
              * @Description: 代理生成器,需要借助SpringAOP來(lái)掃描@RequiresRoles和@RequiresPermissions等注解。生成代理類(lèi)實(shí)現(xiàn)功能增強(qiáng),從而實(shí)現(xiàn)權(quán)限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否則權(quán)限注解無(wú)效。
              * @Param:
              * @return:
              * @Author: Liuzhiliang
              * @Date:
              */ 
              @Bean
              public DefaultAdvisorAutoProxyCreator lifecycleBeanProcessor(){
                  DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
                  defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
                  return defaultAdvisorAutoProxyCreator;
              }

              /** 
              * @Description:  上面配置的DefaultAdvisorAutoProxyCreator相當(dāng)于一個(gè)切面,下面這個(gè)類(lèi)就相當(dāng)于切點(diǎn)了,兩個(gè)一起才能實(shí)現(xiàn)注解權(quán)限控制。
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @Bean
              public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){
                  AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
                  advisor.setSecurityManager(securityManager);
                  return advisor;
              }

              /**
               * @Description: Filter工廠(chǎng),設(shè)置對(duì)應(yīng)的過(guò)濾條件和跳轉(zhuǎn)條件
               * @Param:
               * @return:
               * @Author: Liuzhiliang
               * @Date:
               */

              //權(quán)限管理,配置主要是Realm的管理認(rèn)證
              @Bean
              public DefaultWebSecurityManager securityManager(){
                  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
                  securityManager.setRealm(myShiroRealm());
                  ThreadContext.bind(securityManager);
                  return securityManager;
              }
              //將自己的驗(yàn)證方式加入容器
              @Bean
              public CustomRealm myShiroRealm() {
                  HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
                  //加密
                  matcher.setHashAlgorithmName("md5");
                  matcher.setHashIterations(1);
                  CustomRealm customRealm = new CustomRealm();
                  customRealm.setCredentialsMatcher(matcher);
                  return customRealm;
              }

              @Bean
              public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager){
                  ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
                  shiroFilterFactoryBean.setSecurityManager(securityManager);
          //        Map<String,String> maps = new HashMap<>();
          //        maps.put("/logout","logout");
          //        maps.put("/**","authc");
          //        shiroFilterFactoryBean.setLoginUrl("/login");
          //        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
          //        shiroFilterFactoryBean.setSuccessUrl("/index");
          //        shiroFilterFactoryBean.setFilterChainDefinitionMap(maps);
                  return shiroFilterFactoryBean;
              }

          }

          配置swagger

          package com.unclebb.zlgl.config;

          import com.google.common.base.Predicates;
          import org.springframework.context.annotation.Bean;
          import org.springframework.context.annotation.Configuration;
          import springfox.documentation.builders.ApiInfoBuilder;
          import springfox.documentation.builders.PathSelectors;
          import springfox.documentation.service.ApiInfo;
          import springfox.documentation.service.Contact;
          import springfox.documentation.spi.DocumentationType;
          import springfox.documentation.spring.web.plugins.Docket;
          import springfox.documentation.swagger2.annotations.EnableSwagger2;

          /**
           * @Author unclebb
           * @Description Swagger配置類(lèi)
           * @Date 2021/5/9
           **/
          @Configuration
          @EnableSwagger2
          public class Swagger2Config {

              @Bean
              public Docket webApiConfig(){

                  return new Docket(DocumentationType.SWAGGER_2)
                          .groupName("webApi")
                          .apiInfo(webApiInfo())
                          .select()
                          //過(guò)濾掉admin路徑下的所有頁(yè)面
                          .paths(Predicates.and(PathSelectors.regex("/user/.*")))
                          //過(guò)濾掉所有error或error.*頁(yè)面
                          //.paths(Predicates.not(PathSelectors.regex("/error.*")))
                          .build();

              }

              private ApiInfo webApiInfo(){

                  return new ApiInfoBuilder()
                          .title("網(wǎng)站-API文檔")
                          .description("本文檔描述了網(wǎng)站微服務(wù)接口定義")
                          .version("1.0")
                          .contact(new Contact("qy""http://atguigu.com""[email protected]"))
                          .build();
              }

          }

          配置kaptcha

          package com.unclebb.zlgl.config;

          import com.google.code.kaptcha.impl.DefaultKaptcha;
          import com.google.code.kaptcha.util.Config;
          import org.springframework.context.annotation.Bean;
          import org.springframework.stereotype.Component;

          import java.util.Properties;

          /**
           * @program: zlgl
           * @description: Kaptcha配置類(lèi)
           * @author: LiuZhiliang
           * @create: 2021-05-12 09:03
           **/
          @Component
          public class KaptchaConfig {
              @Bean
              public DefaultKaptcha getKaptcha(){
                  DefaultKaptcha dk = new DefaultKaptcha();
                  Properties properties = new Properties();
                  // 圖片邊框
                  properties.setProperty("kaptcha.border""yes");
                  // 邊框顏色
                  properties.setProperty("kaptcha.border.color""105,179,90");
                  // 字體顏色
                  properties.setProperty("kaptcha.textproducer.font.color""red");
                  // 圖片寬
                  properties.setProperty("kaptcha.image.width""110");
                  // 圖片高
                  properties.setProperty("kaptcha.image.height""40");
                  // 字體大小
                  properties.setProperty("kaptcha.textproducer.font.size""30");
                  // session key
                  properties.setProperty("kaptcha.session.key""code");
                  // 驗(yàn)證碼長(zhǎng)度
                  properties.setProperty("kaptcha.textproducer.char.length""4");
                  // 字體
                  properties.setProperty("kaptcha.textproducer.font.names""宋體,楷體,微軟雅黑");
                  Config config = new Config(properties);
                  dk.setConfig(config);

                  return dk;
              }
          }


          pojo

          User

          package com.unclebb.zlgl.pojo;

          import com.baomidou.mybatisplus.annotation.IdType;
          import com.baomidou.mybatisplus.annotation.TableField;
          import com.baomidou.mybatisplus.annotation.TableId;
          import com.baomidou.mybatisplus.annotation.TableName;
          import lombok.Data;

          import java.util.Set;

          /**
           * @Author unclebb
           * @Description 用戶(hù)實(shí)體類(lèi)
           * @Date 2021/5/9
           **/
          @Data
          @TableName(value = "user")
          public class User {
              @TableId(value = "id",type = IdType.AUTO)//指定自增策略
              private int id;
              @TableField(value = "username")
              private String username;
              @TableField(value = "password")
              private String password;
              @TableField(exist = false)
              private Set<Role> rolesSet;
              private String salt;
          }

          Role

          package com.unclebb.zlgl.pojo;

          import com.baomidou.mybatisplus.annotation.IdType;
          import com.baomidou.mybatisplus.annotation.TableField;
          import com.baomidou.mybatisplus.annotation.TableId;
          import lombok.Data;

          import java.util.Set;

          /**
           * @Author unclebb
           * @Description 角色實(shí)體類(lèi)
           * @Date 2021/5/9
           **/
          @Data
          public class Role {
              @TableId(value = "id",type = IdType.AUTO)//指定自增策略
              private int id;
              @TableField(value = "user_name")
              private String userName;
              @TableField(value = "role_name")
              private String roleName;
              @TableField(exist = false)
              private Set<Permission> permissionSet;
          }


          Permission

          package com.unclebb.zlgl.pojo;

          import com.baomidou.mybatisplus.annotation.IdType;
          import com.baomidou.mybatisplus.annotation.TableField;
          import com.baomidou.mybatisplus.annotation.TableId;
          import lombok.Data;

          /**
           * @Author unclebb
           * @Description 權(quán)限實(shí)體類(lèi)
           * @Date 2021/5/9
           **/
          @Data
          public class Permission {
              @TableId(value = "id",type = IdType.AUTO)//指定自增策略
              private int id;
              @TableField(value = "role_name")
              private String roleName;
              @TableField(value = "permission_name")
              private String permissionName;
          }


          Mapper

          基本格式:

          package com.unclebb.zlgl.mapper;

          import com.baomidou.mybatisplus.core.mapper.BaseMapper;
          import com.unclebb.zlgl.pojo.User;
          import org.apache.ibatis.annotations.Mapper;

          /**
           * @Author unclebb
           * @Description 用戶(hù)映射
           * @Date 2021/5/9
           **/
          @Mapper
          public interface UserMapper extends BaseMapper<User> {
          }


          Service

          Interface

          LoginService

          package com.unclebb.zlgl.service;

          import com.baomidou.mybatisplus.extension.service.IService;
          import com.unclebb.zlgl.pojo.User;
          import org.springframework.stereotype.Service;

          /**
           * @Author unclebb
           * @Description 用戶(hù)登錄接口
           * @Date 2021/5/9
           **/
          @Service
          public interface LoginService extends IService<User> {
              public User getByUsername(String username);
          }


          RoleService

          package com.unclebb.zlgl.service;

          import com.baomidou.mybatisplus.extension.service.IService;
          import com.unclebb.zlgl.pojo.Role;
          import org.springframework.stereotype.Service;

          import java.util.List;

          @Service
          public interface RoleService extends IService<Role> {
              public List<Role> getRole(String userName);
          }


          PermissionService

          package com.unclebb.zlgl.service;

          import com.baomidou.mybatisplus.extension.service.IService;
          import com.unclebb.zlgl.pojo.Permission;
          import org.springframework.stereotype.Service;

          import java.util.List;

          @Service
          public interface PermissionService extends IService<Permission> {
              public List<Permission> getPermissions(String roleName);
          }


          ServiceImpl

          LoginServiceImpl

          package com.unclebb.zlgl.service.impl;

          import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
          import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
          import com.unclebb.zlgl.mapper.UserMapper;
          import com.unclebb.zlgl.pojo.Role;
          import com.unclebb.zlgl.pojo.User;
          import com.unclebb.zlgl.service.LoginService;
          import com.unclebb.zlgl.service.PermissionService;
          import com.unclebb.zlgl.service.RoleService;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;

          import java.util.HashSet;
          import java.util.List;
          import java.util.Set;

          /**
           * @Author unclebb
           * @Description 登錄實(shí)現(xiàn)類(lèi)
           * @Date 2021/5/9
           **/
          @Service
          public class LoginServiceImpl extends ServiceImpl<UserMapper, User> implements LoginService {

              @Autowired
              RoleService roleService;

              @Override
              public User getByUsername(String username) {
                  QueryWrapper<User> wrapper = new QueryWrapper<>();
                  wrapper.eq("username",username);
                  User user = this.getOne(wrapper);
                  List<Role> roleList = roleService.getRole(user.getUsername());
                  user.setRolesSet(new HashSet<Role>(roleList));
                  return user;
              }
          }


          RoleServiceImpl

          package com.unclebb.zlgl.service.impl;

          import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
          import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
          import com.unclebb.zlgl.mapper.RoleMapper;
          import com.unclebb.zlgl.pojo.Permission;
          import com.unclebb.zlgl.pojo.Role;
          import com.unclebb.zlgl.service.PermissionService;
          import com.unclebb.zlgl.service.RoleService;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;

          import java.util.HashSet;
          import java.util.List;
          import java.util.Set;

          /**
           * @program: zlgl
           * @description: Role實(shí)現(xiàn)類(lèi)
           * @author: LiuZhiliang
           * @create: 2021-05-10 16:16
           **/
          @Service
          public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {
              @Autowired
              PermissionService permissionService;
              @Override
              public List<Role> getRole(String userName) {
                  QueryWrapper wrapper = new QueryWrapper();
                  wrapper.eq("user_name",userName);
                  List<Role> roleList = this.list(wrapper);
                  for (Role role:roleList){
                      List<Permission> permissions = permissionService.getPermissions(role.getRoleName());
                      role.setPermissionSet(new HashSet<Permission>(permissions));
                  }
                  return roleList;
              }
          }


          PermissionServiceImpl

          package com.unclebb.zlgl.service.impl;

          import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
          import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
          import com.unclebb.zlgl.mapper.PermissionMapper;
          import com.unclebb.zlgl.pojo.Permission;
          import com.unclebb.zlgl.pojo.User;
          import com.unclebb.zlgl.service.PermissionService;
          import org.springframework.stereotype.Service;

          import java.util.List;
          import java.util.Set;

          /**
           * @program: zlgl
           * @description: Permission實(shí)現(xiàn)類(lèi)
           * @author: LiuZhiliang
           * @create: 2021-05-10 16:18
           **/
          @Service
          public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
              @Override
              public List<Permission> getPermissions(String roleName) {
                  QueryWrapper<Permission> wrapper = new QueryWrapper<>();
                  wrapper.eq("role_name",roleName);
                  return this.list(wrapper);
              }
          }

          Controller

          package com.unclebb.zlgl.controller;

          import com.unclebb.zlgl.pojo.Role;
          import com.unclebb.zlgl.pojo.User;
          import com.unclebb.zlgl.service.RoleService;
          import com.unclebb.zlgl.utils.Result;
          import io.swagger.annotations.ApiOperation;
          import org.apache.shiro.SecurityUtils;
          import org.apache.shiro.authc.AuthenticationException;
          import org.apache.shiro.authc.UsernamePasswordToken;
          import org.apache.shiro.authz.AuthorizationException;
          import org.apache.shiro.session.Session;
          import org.apache.shiro.subject.Subject;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.util.StringUtils;
          import org.springframework.web.bind.annotation.*;

          import javax.servlet.http.HttpSession;
          import java.util.Enumeration;
          import java.util.HashMap;
          import java.util.List;
          import java.util.Map;

          /**
           * @Author unclebb
           * @Description 登錄控制器
           * @Date 2021/5/9
           **/
          @RestController
          public class LoginController {

              @Autowired
              RoleService roleService;

              /** 
              * @Description: 登錄接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @ApiOperation(value = "登錄接口")
              @RequestMapping("/user/login")
              public Result login(@RequestBody User user){
                  System.out.println("進(jìn)入/user/login API接口");
                  if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getPassword())){
                      return Result.fail("請(qǐng)輸入用戶(hù)名密碼");
                  }
                  Subject subject = SecurityUtils.getSubject();
                  Session session = subject.getSession();
                  Object sessionId = session.getId();
                  Map ret = new HashMap<String,Object>();
                  ret.put("token",sessionId);
                  UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
                  try {
                      //登錄成功
                      subject.login(token);
                      return Result.ok(ret);
                  } catch (AuthenticationException e) {
                      e.printStackTrace();
                      //登錄失敗
                      return Result.fail("用戶(hù)名密碼錯(cuò)誤");
                  }
              }

              /** 
              * @Description: 基本測(cè)試接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/noauthority")
              public Result noauthority(){
                  return Result.fail("沒(méi)有權(quán)限");
              }

              
              /** 
              * @Description: 測(cè)試session接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/demoSession")
              @ResponseBody
              public String demoSession(HttpSession session){
                  System.out.println("測(cè)試session");
                  Enumeration<String> names = session.getAttributeNames();
                  while (names.hasMoreElements()){
                      String name = names.nextElement();
                      Object value = session.getAttribute(name);
                      System.out.println(name + " -------  "+ value);
                  }
                  return "session 取值";
              }

              /** 
              * @Description: 測(cè)試session接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/demoSession2")
              @ResponseBody
              public String demoSession2(){
                  Subject subject = SecurityUtils.getSubject();
                  Session session = subject.getSession();
                  System.out.println(session.getHost());
                  System.out.println(session.getId());
                  System.out.println(session.getLastAccessTime().getTime());
                  System.out.println(session.getTimeout());
                  System.out.println(session.getAttribute("test"));
                  return "session 取值";
              }

              /** 
              * @Description: 測(cè)試session接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/checkPermission")
              @ResponseBody
              public Result checkPermission(User user){
                  if (StringUtils.isEmpty(user.getUsername())||StringUtils.isEmpty(user.getPassword())){
                      return Result.fail("請(qǐng)輸入用戶(hù)名密碼");
                  }
                  Subject subject = SecurityUtils.getSubject();
                  Session session = subject.getSession();
                  session.setAttribute("test","test");
                  UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
                  token.setRememberMe(true);
                  try {
                      //登錄成功
                      subject.login(token);
                  } catch (AuthenticationException e) {
                      e.printStackTrace();
                      //登錄失敗
                      return Result.fail("用戶(hù)名密碼錯(cuò)誤");
                  }
                  try {
                      subject.checkRole("admin");
                      return Result.ok("權(quán)限檢查成功");
                  } catch (AuthorizationException e) {
                      e.printStackTrace();
                      return Result.fail("檢查權(quán)限失敗");
                  }
              }

              /** 
              * @Description: 根據(jù)token獲取用戶(hù)授權(quán)信息接口 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/checkRole")
              public Result checkRole(@RequestParam String token){
                  Subject subject = SecurityUtils.getSubject();
                  Session session = subject.getSession();
                  List<Role> roleList = null;
                  if (token.equals(session.getId().toString())){
                      String username = session.getAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY").toString();
                      System.out.println(username);
                      roleList = roleService.getRole(username);
                  }
                  return Result.ok(roleList);
              }
              
              /** 
              * @Description: 測(cè)試kaptcha ,獲取驗(yàn)證碼
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/testKaptcha")
              @ResponseBody
              public String TestKaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
                  byte[] captcha = null;
                  ByteArrayOutputStream out = new ByteArrayOutputStream();

                  try {
                      // 將生成的驗(yàn)證碼保存在session中
                      String createText = defaultKaptcha.createText();
                      request.getSession().setAttribute("rightCode", createText);
                      BufferedImage bi = defaultKaptcha.createImage(createText);
                      ImageIO.write(bi, "jpg", out);
                  } catch (Exception e) {
                      response.sendError(HttpServletResponse.SC_NOT_FOUND);
                  }

                  captcha = out.toByteArray();
                  response.setHeader("Cache-Control""no-store");
                  response.setHeader("Pragma""no-cache");
                  response.setDateHeader("Expires", 0);
                  response.setContentType("image/jpeg");
                  ServletOutputStream sout = response.getOutputStream();
                  sout.write(captcha);
                  sout.flush();
                  sout.close();
                  return "測(cè)試Kaptcha";
              }

              /**
               * 校對(duì)驗(yàn)證碼
               *
               * @param request
               * @param response
               * @return
               */
              @RequestMapping(value = "/user/verifyKaptcha")
              public Result imgvrifyControllerDefaultKaptcha(HttpServletRequest request, HttpServletResponse response) {
                  ModelAndView model = new ModelAndView();
                  String rightCode = (String) request.getSession().getAttribute("rightCode");
                  String tryCode = request.getParameter("tryCode");
                  System.out.println("rightCode:" + rightCode + " ———— tryCode:" + tryCode);
                  if (!rightCode.equals(tryCode)) {
                      model.addObject("info""驗(yàn)證碼錯(cuò)誤,請(qǐng)?jiān)佥斠淮?");
                      model.setViewName("login");
                      return Result.fail("驗(yàn)證碼錯(cuò)誤");
                  } else {
                      model.addObject("info""登陸成功");
                      model.setViewName("index");
                      return Result.ok("驗(yàn)證成功");
                  }
              }

            /** 
              * @Description: 測(cè)試 校驗(yàn)權(quán)限 permission 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/testShiroPermission")
              @RequiresPermissions("user:add")
              public Result TestShiroPermissions(){
                  System.out.println("訪(fǎng)問(wèn) TestShiroPermissions API");
                  Subject subject = SecurityUtils.getSubject();
                  String username = (String) subject.getPrincipal();
                  System.out.println(username);
                  return Result.ok(username);
              }

              /** 
              * @Description: 登出功能API
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/logout")
              public Result logout(){
                  Subject subject = SecurityUtils.getSubject();
                  String username = (String) subject.getPrincipal();
                  subject.logout();
                  return Result.ok(username);
              }
              /** 
              * @Description:  測(cè)試校驗(yàn) 角色 role
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @RequestMapping("/user/TestRole")
              @RequiresRoles("admin")
              public Result TestRole(){
                  System.out.println("測(cè)試TestRole");
                  return Result.ok("測(cè)試Role");
              }

          }


          util

          Result

          package com.unclebb.zlgl.utils;

          import io.swagger.annotations.ApiModel;
          import io.swagger.annotations.ApiModelProperty;
          import lombok.Data;

          /**
           * @Author unclebb
           * @Description 統(tǒng)一返回API格式
           * @Date 2021/5/9
           **/
          @Data
          @ApiModel(value = "全局統(tǒng)一返回結(jié)果")
          public class Result<T> {

              @ApiModelProperty(value = "返回碼")
              private Integer code;

              @ApiModelProperty(value = "返回消息")
              private String message;

              @ApiModelProperty(value = "返回?cái)?shù)據(jù)")
              private T data;

              public Result(){}

              public static <T> Result<T> build(T data) {
                  Result<T> result = new Result<T>();
                  if (data != null)
                      result.setData(data);
                  return result;
              }

              public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
                  Result<T> result = build(body);
                  result.setCode(resultCodeEnum.getCode());
                  result.setMessage(resultCodeEnum.getMessage());
                  return result;
              }

              public static<T> Result<T> ok(){
                  return Result.ok(null);
              }

              /**
               * 操作成功
               * @param data
               * @param <T>
               * @return
               */
              public static<T> Result<T> ok(T data){
                  Result<T> result = build(data);
                  return build(data, ResultCodeEnum.SUCCESS);
              }

              public static<T> Result<T> fail(){
                  return Result.fail(null);
              }

              /**
               * 操作失敗
               * @param data
               * @param <T>
               * @return
               */
              public static<T> Result<T> fail(T data){
                  Result<T> result = build(data);
                  return build(data, ResultCodeEnum.FAIL);
              }

              public Result<T> message(String msg){
                  this.setMessage(msg);
                  return this;
              }

              public Result<T> code(Integer code){
                  this.setCode(code);
                  return this;
              }
          }


          ResultCode

          package com.unclebb.zlgl.utils;

          import lombok.Getter;

          /**
           * @Author unclebb
           * @Description API狀態(tài)信息
           * @Date 2021/5/9
           **/
          @Getter
          public enum ResultCodeEnum {

              SUCCESS(200,"成功"),
              FAIL(201, "失敗"),
              SERVICE_ERROR(202, "服務(wù)異常"),
              DATA_ERROR(204, "數(shù)據(jù)異常"),

              SIGN_ERROR(300, "簽名錯(cuò)誤"),

              PAY_PASSWORD_ERROR(401, "支付密碼錯(cuò)誤"),
              REPEAT_ERROR(402, "重復(fù)提交"),

              INVEST_AMMOUNT_MORE_ERROR(501, "出借金額已經(jīng)多余標(biāo)的金額"),
              RETURN_AMMOUNT_MORE_ERROR(502, "還款金額不正確"),
              PROJECT_AMMOUNT_ERROR(503, "標(biāo)的金額不一致")
              ;

              private Integer code;

              private String message;

              private ResultCodeEnum(Integer code, String message) {
                  this.code = code;
                  this.message = message;
              }
          }


          CustomRealm

          package com.unclebb.zlgl.utils;

          import com.unclebb.zlgl.pojo.Permission;
          import com.unclebb.zlgl.pojo.Role;
          import com.unclebb.zlgl.pojo.User;
          import com.unclebb.zlgl.service.LoginService;
          import org.apache.shiro.authc.AuthenticationException;
          import org.apache.shiro.authc.AuthenticationInfo;
          import org.apache.shiro.authc.AuthenticationToken;
          import org.apache.shiro.authc.SimpleAuthenticationInfo;
          import org.apache.shiro.authz.AuthorizationInfo;
          import org.apache.shiro.authz.SimpleAuthorizationInfo;
          import org.apache.shiro.realm.AuthorizingRealm;
          import org.apache.shiro.subject.PrincipalCollection;
          import org.apache.shiro.util.ByteSource;
          import org.springframework.beans.factory.annotation.Autowired;

          /**
           * @program: zlgl
           * @description: 自定義Realm
           * @author: LiuZhiliang
           * @create: 2021-05-10 09:09
           **/
          public class CustomRealm extends AuthorizingRealm {

              @Autowired
              LoginService loginService;

              /** 
              * @Description: 授權(quán)配置
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @Override
              protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
                  String username = (String) principals.getPrimaryPrincipal();
                  User user = loginService.getByUsername(username);
                  if (user == null){
                      return null;
                  }else {
                      SimpleAuthorizationInfo  simpleAuthorizationInfo = new SimpleAuthorizationInfo();
                      for (Role role : user.getRolesSet()){
                          simpleAuthorizationInfo.addRole(role.getRoleName());
                          for (Permission permission : role.getPermissionSet()){
                              simpleAuthorizationInfo.addStringPermission(permission.getPermissionName());
                          }
                      }
                      return simpleAuthorizationInfo;
                  }
              }

              /** 
              * @Description: 認(rèn)證配置 
              * @Param:  
              * @return:  
              * @Author: Liuzhiliang
              * @Date:  
              */ 
              @Override
              protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
                  String username = token.getPrincipal().toString();
                  User user = loginService.getByUsername(username);
                  if (user == null){
                      return null;
                  }else {
                      //匹配密碼
                      SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,user.getPassword(),getName());
                      simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
                      return simpleAuthenticationInfo;
                  }
              }
          }


          前端代碼

          前端我這里直接用了 開(kāi)源的管理系統(tǒng)框架
          附地址:

          https://github.com/PanJiaChen/vue-admin-template

          運(yùn)行截圖如下

          完事兒只需要改一下它的 返回狀態(tài)碼校驗(yàn),配置下跨域就可以了

          整合驗(yàn)證碼

          驗(yàn)證碼部分包含兩個(gè)API接口

          /user/testKaptcha 獲取驗(yàn)證碼信息
          /user/verifyKaptcha 校驗(yàn)

          其中獲取驗(yàn)證碼圖片信息相當(dāng)于請(qǐng)求靜態(tài)圖片資源,直接將驗(yàn)證碼圖片的src指向 該接口即可,前端源碼如下:

                    <el-image :src="kaptcha" @click="refreshCode()" alt="加載失敗" style="margin-left:10px;height:40px;margin-top:5px">
                      <div slot="placeholder" class="image-slot">
                          <i class="el-icon-loading"></i>
                      </div>
                    </el-image>

          其中路徑定義為:

          kaptcha:"http://localhost:8082/user/testKaptcha?t="+ new Date().getTime(),

          后面加的時(shí)間參數(shù)是為了刷新url用的
          前端的刷新函數(shù)就是將kaptcha重新賦值

              refreshCode(){
                console.log("測(cè)試切換驗(yàn)證碼")
                this.kaptcha = "http://localhost:8082/user/testKaptcha?t="+ new Date().getTime()
                console.log(this.kaptcha)
              },

          登錄、權(quán)限校驗(yàn)、登出效果如下

          登錄

          登錄首先會(huì)驗(yàn)證 驗(yàn)證碼的正確性,登陸成功進(jìn)入主界面

          驗(yàn)證碼錯(cuò)誤如下:

          用戶(hù)名密碼錯(cuò)誤如下:

          登陸成功后請(qǐng)求校驗(yàn)角色 校驗(yàn)成功
          請(qǐng)求校驗(yàn)權(quán)限 校驗(yàn)成功

          退出,執(zhí)行兩次,data為null

          再次校驗(yàn)權(quán)限,報(bào)出異常

          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/lzl980111/article/details/116662930






          粉絲福利:Java從入門(mén)到入土學(xué)習(xí)路線(xiàn)圖

          ??????

          ??長(zhǎng)按上方微信二維碼 2 秒


          感謝點(diǎn)贊支持下哈 

          瀏覽 80
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  靠逼网站免费 | 在线无码高清播放 | 精品无码一区二区三区四区久久久 | www.xxx操逼网 | xjgggyxgs.com高价收liang,请涟系@qdd2000 |