资讯专栏INFORMATION COLUMN

shiro项目介绍

ruicbAndroid / 329人阅读

摘要:项目介绍在之前的整合项目之后,更加完善功能,之前的代码不予展示与介绍,想了解的请参考整合项目项目代码获取功能新增用户注册登录错误次数限制使用作缓存注解配置引入数据校验使用统一异常处理配置项目结构代码控制层,以下展示注册和登录功能会跳到我们自

shiro项目介绍

在之前的shiro整合项目之后,更加完善shiro功能,之前的代码不予展示与介绍,想了解的请参考shiro整合项目
项目代码获取:https://github.com/pysasuke/s...

功能新增

用户注册

登录错误次数限制(使用redis作缓存)

shiro注解配置

DTO引入

数据校验(使用hibernate validation)

SpringMVC统一异常处理配置

项目结构 java:代码

controller:控制层,以下展示注册和登录功能

    @RequestMapping("/login")
    public String login(ShiroUser shiroUser, HttpServletRequest request) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(shiroUser.getUsername(), shiroUser.getPassword());
        try {
            subject.login(token);//会跳到我们自定义的realm中
            request.getSession().setAttribute("user", shiroUser);
            log.info(shiroUser.getUsername() + "登录");
            return "user/success";
        } catch (UnknownAccountException e) {
            return "user/login";
        } catch (IncorrectCredentialsException e) {
            request.setAttribute("error", "用户名或密码错误");
            return "user/login";
        } catch (ExcessiveAttemptsException e) {
            request.setAttribute("error", "输入密码错误太多次,请稍后再试!");
            return "user/login";
        } catch (Exception e) {
            request.setAttribute("error", "未知错误");
            return "user/login";
        }
    }
    
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String register(Model model,
                           @Valid @ModelAttribute ShiroUserDTO shiroUserDTO, BindingResult bindingResult) {
        //数据校验
        if (bindingResult.hasErrors()) {
            List allErrors = bindingResult.getAllErrors();
            for (ObjectError objectError : allErrors) {
                //输出错误信息
                System.out.println(objectError.getDefaultMessage());
            }
            model.addAttribute("error", "填入信息有误");
            model.addAttribute("user", shiroUserDTO);
            return "/user/register";
        }
        if (shiroUserService.getByUsername(shiroUserDTO.getUsername()) == null) {
            shiroUserService.insertUser(shiroUserDTO);
            return "redirect:/";
        } else {
            model.addAttribute("user", shiroUserDTO);
            model.addAttribute("error", "userName has been registered!");
            return "/user/register";
        }
    }

service:业务处理层,以下展示新增用户功能,包含数据转换(DTO到Entity)和密码加密(shiro加密策略)

 public void insertUser(ShiroUserDTO shiroUserDTO) {
        ShiroUser shiroUser = converToAddress(shiroUserDTO);
        shiroUserMapper.insert(shiroUser);
    }
  
 private ShiroUser converToAddress(ShiroUserDTO shiroUserDTO) {
        ShiroUser shiroUser = new ShiroUser();
        BeanUtils.copyProperties(shiroUserDTO, shiroUser);
        passwordEncrypt(shiroUser);
        shiroUser.setCreatetime(new Date());
        shiroUser.setRoleId(1);
        return shiroUser;
    }

  private void passwordEncrypt(ShiroUser shiroUser) {
        String username = shiroUser.getUsername();
        String password = shiroUser.getPassword();
        String salt2 = new SecureRandomNumberGenerator().nextBytes().toHex();
        int hashIterations = 3;
        String algorithmName = "md5";
        SimpleHash hash = new SimpleHash(algorithmName, password,
                username + salt2, hashIterations);
        String encodedPassword = hash.toHex();
        shiroUser.setSalt(salt2);
        shiroUser.setPassword(encodedPassword);
    }

dao:数据库交互层

entity:实体对象层,以下展示数据校验

@Data
public class ShiroUser {
    private Integer id;
    
    @NotNull(message = "用户名不能为空")
    @Size(min = 3, max = 16, message = "用户名长度必须介于3-16个字符之间")
    
    private String username;
    
    @NotNull(message = "密码不能为空")
    @Size(min = 3, max = 16, message = "{密码长度必须介于3-16个字符之间")
    private String password;
    
    private Date createtime;
    
    private Date lasttime;
    
    @Email(message = "请输入正确的邮箱")
    private String email;
    
    private String sex;
    
    private String salt;
    
    private Integer roleId;
}

realm:自定义Realm(shiro相关),以下加入了加密相关代码

public class MyRealm extends AuthorizingRealm {

    @Resource
    private ShiroUserService shiroUserService;

    // 为当前登陆成功的用户授予权限和角色,已经登陆成功了
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        String username = (String) principals.getPrimaryPrincipal(); //获取用户名
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.setRoles(shiroUserService.getRoles(username));
        authorizationInfo.setStringPermissions(shiroUserService.getPermissions(username));
        return authorizationInfo;
    }

    // 验证当前登录的用户,获取认证信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        String username = (String) token.getPrincipal(); // 获取用户名
        ShiroUser shiroUser = shiroUserService.getByUsername(username);
        if (shiroUser != null) {
            SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(shiroUser.getUsername(), shiroUser.getPassword(), "myRealm");
            //通过SimpleAuthenticationInfo的credentialsSalt设置盐,HashedCredentialsMatcher会自动识别这个盐。
            authcInfo.setCredentialsSalt(ByteSource.Util.bytes(shiroUser.getUsername() + shiroUser.getSalt()));
            return authcInfo;
        } else {
            return null;
        }
    }
}

constants:常量类包

dto:DTO对象包,以下展示ShiroUserDTO(只包含交互相关的字段)

@Data
public class ShiroUserDTO {

    @NotNull(message = "用户名不能为空")
    @Size(min = 3, max = 16, message = "用户名长度必须介于3-16个字符之间")
    private String username;

    @NotNull(message = "密码不能为空")
    @Size(min = 3, max = 16, message = "{密码长度必须介于3-16个字符之间")
    private String password;

    @Email(message = "请输入正确的邮箱")
    private String email;

    @NotNull(message = "请选择性别")
    private String sex;
}

credentials:处理重试次数类包

public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    @Autowired
    private RedisCache redisCache;


    //匹配用户输入的token的凭证(未加密)与系统提供的凭证(已加密)
    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        String username = (String) token.getPrincipal();
        //retry count + 1
        //AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减。
        AtomicInteger retryCount = redisCache.getCache(Constants.USER + username, AtomicInteger.class);
        if (retryCount == null) {
            retryCount = new AtomicInteger(0);
        }
        //增长
        if (retryCount.incrementAndGet() > 5) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        }
        redisCache.putCacheWithExpireTime(Constants.USER + username, retryCount, 600);
        boolean matches = super.doCredentialsMatch(token, info);
        if (matches) {
            //clear retry count
            redisCache.deleteCache(Constants.USER + username);
        }
        return matches;
    }
}
resources:配置文件

application.xml:spring配置文件入口,加载spring-config.xml

spring-mvc.xml:springmvc配置相关文件

spring-config.xml:加载其他集成的配置文件,这里加载spring-mybatis.xml、spring-shiro.xml和db.properties

spring-mybatis.xml:mybatis相关配置文件

spring-shiro.xml:shiro配置相关文件

    
    
        
        
        
        
        
        
    

    
    
        
    
    
     
    
        
            
                
                
                    redirect:/user/login
                
                
                
                    redirect:/user/login
                
            
        
        
        
    

db.properties:数据库相关参数配置

log4j.properties:日志相关参数配置

mapping:存放mybatis映射文件,以UserMapper.xml为例

redis.properties:redis相关参数配置

#redis config
redis.pool.maxTotal=100
redis.pool.maxIdle=10
redis.pool.maxWaitMillis=5000
redis.pool.testOnBorrow=true
redis.pool.maxActive= 100
redis.pool.maxWait= 3000


#redis ip和端口号
redis.ip=127.0.0.1
redis.port=6379
redis.pass=

spring-redis.xml:redis相关配置

 
    
        
        
        
        
    

    
    
        
        
        
        
    

    
    
        
    

spring-mvc-shiro.xml:shiro注解相关配置

 
    
    
        
    
webapp:web相关

web.xml

 
    
        shiroFilter
        org.springframework.web.filter.DelegatingFilterProxy
        
            
            targetFilterLifecycle
            true
        
    
    
        shiroFilter
        /*
    
 其他文件 logs:日志存放 deploy:部署文件(sql)

update.sql

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `t_permission`
-- ----------------------------
DROP TABLE IF EXISTS `t_permission`;
CREATE TABLE `t_permission` (
  `id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  `permissionname` varchar(100) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ("1", "1", "user:create");
INSERT INTO `t_permission` VALUES ("2", "2", "user:update");
INSERT INTO `t_permission` VALUES ("3", "1", "user:update");

-- ----------------------------
-- Table structure for `t_role`
-- ----------------------------
DROP TABLE IF EXISTS `t_role`;
CREATE TABLE `t_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `rolename` varchar(20) COLLATE utf8mb4_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ("1", "teacher");
INSERT INTO `t_role` VALUES ("2", "student");

-- ----------------------------
-- Table structure for `t_user`
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userName` varchar(20) NOT NULL,
  `password` varchar(50) NOT NULL,
  `createTime` date DEFAULT NULL,
  `lastTime` datetime DEFAULT NULL,
  `email` varchar(256) DEFAULT NULL,
  `sex` enum("male","female") DEFAULT "male",
  `salt` varchar(50) DEFAULT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES ("1", "admin", "86c4604b628d4e91f5f2a2fed3f88430", "2017-08-28", null, "404158848@qq.com", "male", "26753209835f4c837066d1cc7d9b46aa", "1");
INSERT INTO `t_user` VALUES ("2", "test", "a038892c7b638aad0357adb52cabfb29", "2017-08-28", null, "404158848@qq.com", "male", "6ced07d939407fb0449d92d9f17cfcd1", "2");
INSERT INTO `t_user` VALUES ("3", "test1", "4be958cccb89213221888f9ffca6969b", "2017-08-28", null, "404158848@qq.com", "male", "c95a278e52daf5166b1ffd6436cde7b7", "1");
pom.xml:maven相关
        
        
            redis.clients
            jedis
            2.8.0
        
        
            org.springframework.data
            spring-data-redis
            1.6.4.RELEASE
        
        
            com.dyuproject.protostuff
            protostuff-core
            1.0.8
        

        
            com.dyuproject.protostuff
            protostuff-runtime
            1.0.8
        
        

        
        
        
            org.hibernate
            hibernate-validator
            5.0.2.Final
        
        

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70330.html

相关文章

  • Shiro权限管理(一)——介绍

    摘要:大家好,今天给大家分享一个权限管理的框架的,说实话本来我是准备看的,毕竟是家族的框架,和整合更加容易一些。官方给出的介绍是是一个强大且易用的安全框架执行身份验证授权密码学和会话管理。由此可知,的主要功能是认证授权加密密和会话管理。 showImg(https://segmentfault.com/img/bV1BsT?w=1726&h=256); 大家好,今天给大家分享一个权限管理的框...

    liuhh 评论0 收藏0
  • Shiro权限管理(一)——介绍

    摘要:大家好,今天给大家分享一个权限管理的框架的,说实话本来我是准备看的,毕竟是家族的框架,和整合更加容易一些。官方给出的介绍是是一个强大且易用的安全框架执行身份验证授权密码学和会话管理。由此可知,的主要功能是认证授权加密密和会话管理。 showImg(https://segmentfault.com/img/bV1BsT?w=1726&h=256); 大家好,今天给大家分享一个权限管理的框...

    王伟廷 评论0 收藏0
  • spring-springmvc-mybatis-shiro项目介绍

    摘要:项目介绍在之前的整合项目之后,新增日志简单集成,之前的代码不予展示与介绍,想了解的请参考整合项目项目代码获取项目结构代码控制层,,主要包含登录及几个页面跳转会跳到我们自定义的中登录用户名或密码错误业务处理层,包含一个包,以接口类型存在 spring-springmvc-mybatis-shiro项目介绍 在之前的mybatis整合项目之后,新增日志、简单集成shiro,之前的代码不予展...

    fanux 评论0 收藏0
  • Shiro的统一认证授权

    摘要:的统一认证授权是下面的一个简单,易用的权限框架,对于单体应用来讲,完全能够极好的,快速的满足权限的需求,所以一般在做项目的时候,都会成为开发者的首选。 Shiro的统一认证授权 Shiro是Apache下面的一个简单,易用的Java权限框架,对于单体应用来讲,Shiro完全能够极好的,快速的满足权限的需求,所以一般在做项目的时候,Shiro都会成为开发者的首选。 可是,如果你需要做第二...

    cocopeak 评论0 收藏0
  • Shiro实战(一) Shiro核心概念

    摘要:是什么是功能强大简单易用的安全框架,核心功能包括认证授权加密以及管理。的主要作用就是用来执行认证和授权的逻辑,它其实就相当于与安全数据用户账号密码角色权限之间进行交互的桥梁。至此,的三个核心概念已经介绍完毕。 1、Shiro是什么 Shiro是功能强大、简单易用的Java安全框架,核心功能包括:认证、授权、加密以及Session管理。Shiro的应用范围很广泛,小型移动端应用、大型We...

    mdluo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<