发表于: 2019-12-11 22:06:10

2 1176


今天做了什么:

前台-学生证接口都调试成功.

Spring Boot整合Shiro:

shiro的配置:

@Configuration
public class ShiroConfig {
   /**
    * 一个过滤器,拦截url
    */
   @Bean(name = "shiroFilter")
   public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
       ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
       //必须set项
       shiroFilterFactoryBean.setSecurityManager(securityManager);
       //设置登录页面
       shiroFilterFactoryBean.setLoginUrl("/login");
       //设置登录成功跳转页面
       shiroFilterFactoryBean.setSuccessUrl("/backDesk");
       //权限不足跳转的页面
       shiroFilterFactoryBean.setUnauthorizedUrl("/noAuthc");
       //拦截器,下面的属性就是配置不会被拦截的url
       Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
       // authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问,封装在DefaultWebSecurityManager中
       filterChainDefinitionMap.put("/home","anon");
       filterChainDefinitionMap.put("/login/0","anon");
       filterChainDefinitionMap.put("/register/0","anon");
       filterChainDefinitionMap.put("/register/1","anon");
       filterChainDefinitionMap.put("/logout","logout");
       //设置权限拦截器,当权限为superManager才能访问后台    
       
     filterChainDefinitionMap.put("/student/backDesk","authc,perms[/student/backDesk]");
       //这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证
       filterChainDefinitionMap.put("/**", "authc");
       shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
       return shiroFilterFactoryBean;
   }
   @Bean
   public SecurityManager securityManager() {
     DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
     //关联Realm
     defaultWebSecurityManager.setRealm(accountRealm());
      return defaultWebSecurityManager;
   }
   /**
    * 加入加密配置
    * @return
    */
   @Bean(name = "credentialsMatcher")
   public HashedCredentialsMatcher hashedCredentialsMatcher() {
       HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
       // 散列算法:这里使用MD5算法;
       hashedCredentialsMatcher.setHashAlgorithmName("md5");
       // 散列的次数,比如散列两次,相当于 md5(md5(""));
       hashedCredentialsMatcher.setHashIterations(2);
       // storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
       hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
       return hashedCredentialsMatcher;
   }
   /**
    * 创建Realm以便调用
    * @return
    */
   @Bean
   public AccountRealm accountRealm() {
       AccountRealm accountRealm = new AccountRealm();
       // 告诉realm,使用credentialsMatcher加密算法类来验证密文
       accountRealm.setCredentialsMatcher(hashedCredentialsMatcher());
       accountRealm.setCachingEnabled(false);
       return accountRealm;
   }
}

定义的Realm:()

public class AccountRealm extends AuthorizingRealm {
   @Autowired
   private AccountService accountService;
   /**
    * 用户授权
    * 因为暂时没用到授权所以注释了
    **/
   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(
       PrincipalCollection principalCollection) {
       System.out.println("===执行授权===");
//
//        Subject subject = SecurityUtils.getSubject();
//        Account account = (Account) subject.getPrincipal();
//
//        if(account != null){
//            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//            // 角色与权限字符串集合
//            Collection<String> rolesCollection = new HashSet<>();
//            Collection<String> permissionCollection = new HashSet<>();
//   // 读取并赋值用户角色与权限
//            Set<RoleBean> roles = user.getRole();
//            for(RoleBean role : roles){
//                rolesCollection.add(role.getName());
//                Set<PermissionBean> permissions = role.getPermissions();
//                for (PermissionBean permission : permissions){
//                    premissionCollection.add(permission.getUrl());
//                }
//                info.addStringPermissions(premissionCollection);
//            }
//            info.addRoles(rolesCollection);
//            return info;
//        }
       return null;
   }
   /**
    * 用户认证
    **/
   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       System.out.println("开始执行认证");
       //从token中获取principal和credentials.相当于账号和密码
       String username = (String) authenticationToken.getPrincipal();
       String pwd = new String((char[]) authenticationToken.getCredentials());
       //根据name从数据库中查user
       Account account = accountService.findByName(username);
       System.out.println("token.username: "+username);
       System.out.println("findByName: "+account);
       if (account != null){
           // 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验
           //参数1.用户认证的对象(subject.getPrincipal();返回的对象),
           //参数2.从数据库根据用户名查询到的用户的密码
           //参数3.把当前自定义的realm对象传给SimpleAuthenticationInfo,在配置文件需要注入
           System.out.println("return simpleAuthInfo");
           return new SimpleAuthenticationInfo(account.getUsername(), account.getPassword(),getName());
       }
       return null;
   }
}

controller:

@PostMapping("/login")
   public String login(String username,String password){
       //1.根据账密生成token
       UsernamePasswordToken token = new UsernamePasswordToken(username,password);
       //2.获取当前用户对象
       Subject currentUser = SecurityUtils.getSubject();
       try {
           //3.进行认证
           //在调用了login方法后,SecurityManager会收到AuthenticationToken,并将其发送给已配置的Realm执行必须的认证检查
           //每个Realm都能在必要时对提交的AuthenticationTokens作出反应
           //所以这一步在调用login(token)方法时,它会走到MyRealm.doGetAuthenticationInfo()方法中,具体验证方式详见此方法
           log.error("对用户[" + username + "]进行登录验证");
           currentUser.login(token);
           log.error("验证通过");
       }catch (UnknownAccountException uae){
           log.error("对用户[" + username + "]进行登录验证..验证未通过,未知的用户");
       }catch(IncorrectCredentialsException ice){
           log.error("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
       }catch(LockedAccountException lae){
           log.error("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
       }catch(ExcessiveAttemptsException eae){
           log.error("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
       }catch(AuthenticationException ae){
           //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景
           log.error("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
           ae.printStackTrace();
       }
       //验证是否登录成功
       if(currentUser.isAuthenticated()){
           log.info("用户[" + username + "]登录认证通过");
           return "登录成功";
       }else{
           token.clear();
           //重定向到登录处
           return "redirect:/login";
       }
   }

但是还没调通.

报token验证失败错误. username是存在的, password没验证通过, 推测是跟加密有关,明天再弄弄加密.

收获.

问题:

1.SpringBoot 找不到或无法加载主类

2.SpringBoot无法返回视图,报404

3.Spring返回视图报circular view path错误

总结是对spring boot的模板引擎很不熟悉 , 毕竟跟jsp的那一套不同.

明天计划:

继续shiro登录认证, 然后做授权.




返回列表 返回列表
评论

    分享到