首先说明一下,整合shrio主要需要我们独立书写的是配置类与Controller层shrio的核心对象subject,所以这里只贴了配置类与Controller层,而且博主也是才接触到shiro,如果有什么解析的不太对的,还望指出大家一起进步:
首先需要独立引入依赖:
<!--导入shrio核心依赖--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.4.0</version> </dependency> <!--这个是阿帕奇老铁的工具类,集合判空很好用,还有很多其他功能,反正爽就对了--> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency>Shrio的配置类之AuthRealm:
/** * 认证授权的配置类,主要还是与数据源打交道的 */ public class AuthRealm extends AuthorizingRealm { @Autowired private UserService userService; @Override /** * 作为授权使用,需要覆盖这个方法来实现 * */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //授权实际上是在认证登录以后,把获取的User对象放入到了session中 //将session中的user对象取出来,使用的是principals.fromRealm这个方法 //传入的参数是这个类的名字,我们使用迭代器,进行遍历,将其取出 User user= (User) principals.fromRealm(this.getClass().getName()).iterator().next(); //声明权限的集合 List<String> permissionList = new ArrayList<>(); //声明角色的集合 List<String> roleNameList= new ArrayList<>(); //拿到当前所有的角色 Set<Role> roles = user.getRoles(); //遍历所有的角色 //实现判断一下角色集合,只有当角色集合不为空的时候才能进行判断 if (CollectionUtils.isNotEmpty(roles)){ //将角色挨个遍历出来 for (Role role: roles){ //每次遍历角色的时候,将角色名取出来放进提前定义好的角色集合里 roleNameList.add(role.getRname()); //再拿到每个角色的权限列表 Set<Permission> permissions = role.getPermissions(); if ( CollectionUtils.isNotEmpty(permissions)){ for (Permission permission:permissions){ //将每一个权限的name放到我们之前定义好的permissionLiST里 //因为我们本质上还是根据permissionname进行判断一个用户是否有某个权限 permissionList.add(permission.getName()); } } } } //创建实例zationInfo的实例,将我们获取到的权限加入到对象中 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //将权限授权添加给授权信息实例(SimpleAuthorizationInfo) info.addStringPermissions(permissionList); //处理simpleAuthorizationInfo的时候,同样为他加上角色授权 info.addRoles(roleNameList); return info; } @Override /** * 作为认证登录使用,需要覆盖这个方法来实现 */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //1.将传入的token强转为shiro的UsernamePasswordToken类型 UsernamePasswordToken usernamePasswordToken=(UsernamePasswordToken) token; //2.从里面取出对应的Username String username = usernamePasswordToken.getUsername(); //3.调用我们之前写过的根据Username查询User实体的方法,得到User实体 User user = userService.findByUserName(username); //4.将用户里的数据转换成AuthenticationInfo对象 //传入参数为:刚查询到的user对象,密码,当前这个类的名字(我们通过反射获得) SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getClass().getName()); //返回就行了 return simpleAuthenticationInfo; } }shiro的配置类之CredentialMatcher:
/** * 继承shrio为我们提供的Matcher接口,从而实现自定义加密规则的功能,然后再将这个类注入到 * AuthRealm中就好 */ public class CredentialMatcher extends SimpleCredentialsMatcher { /** * 覆盖重写默认的Match的方法 * * @param token * @param info * @return */ @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { //将传递过来的token转化成UsernamePasswordToken UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; //从usernamePasswordToken中取出password //但是这个类返回的值是char型数组,我们需要将其转换成string //这是前端传递过来的密码 String password = new String(usernamePasswordToken.getPassword()); //现在我们需要再拿出我们数据库里的密码,也就是我们刚才为info对象传入的值 String dbpassword = (String) info.getCredentials(); //这样两个密码都有了,中间规则就可以由我们来定义了 //我们这里就直接看它两个是否相同就好了 //这里的this代指的是SimpleCredentialsMatcher对象 return this.equals(password, dbpassword); } }主要还是登录功能,引入了Shiro的核心对象subject的介绍
jsp页面就省略不写了,不过springboot2整合jsp页面教程网上也一堆,等我以后再写吧基本上就是加依赖建包没啥了
@Controller public class DemoController { /** * 直接访问login页面 * @return */ @RequestMapping("/login") public String login(){ return "login"; } /** * 登录后的页面 * @return */ @RequestMapping("/index") public String index(){ return "index"; } /** * 初始的登录页面 */ @RequestMapping("/loginUser") public String loginUser(@RequestParam("username") String username, @RequestParam("password") String password, HttpSession session ){ //根据前端传递过来的name和passowrd生成shrio的UsernamePasswordToken UsernamePasswordToken token = new UsernamePasswordToken(username, password); //写shiro的认证逻辑 Subject subject = SecurityUtils.getSubject(); //因为可能出现异常,所以直接try catch try { //调用login方法,传入token subject.login(token); //如果登录没有出现异常的话,就可以通过getPrincinpal()获取登录用户 User user= (User)subject.getPrincipal(); //将登录用户写到session里 session.setAttribute("user",user); //执行成功返回到index页面 return "index"; } catch (AuthenticationException e) { e.printStackTrace(); //出错的话返回登录页面 return "login"; } } /** * 定义一个退出登录的controller * @return */ @RequestMapping("/logout") public String logout() { //同样是通过实例化subject,进行权限与登录登出的逻辑操作 //SecurityUtils 是一个抽象类。并且没有任何子类。在其中声明了一个静态属性,三个静态方法。 //静态属性 securityManager-->用来存储当前应用中全局唯一的一个SecurityManager。 // getSubject 静态方法-->这个是 Shiro 中最核心的方法了,用来获取 Subject. //Subject是Shiro的核心对象,基本所有身份验证、授权都是通过Subject完成 Subject subject = SecurityUtils.getSubject(); if (subject != null) { subject.logout(); } return "login"; } /** * 只有绑定了管理员权限(角色)的用户才能访问admin接口 * 而绑定是在shiroConfiguration里进行的 * @return */ @RequestMapping("/admin") @ResponseBody public String admin() { return "admin success"; } }稍微总结一下,如果只看实现的话,我们主要需要运用到shiro的subject对象的各种api,以及shrio核心配置类对不同路径的访问定义不同的权限,至于shrio的延伸,以后应该会更新,另外这里说明一下,这里有好多别人的内容,但是我忘记我学的时候从哪粘贴的了,反正这里先道声抱歉,如果谁看到了可以告诉我,我加一下它的链接
最后补充一点:IDEA中的mavenhelper插件真好用!!!