shiro登录认证

<!--添加日志功能-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
        </dependency>

        <!--添加shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.1</version>
        </dependency>
        <!--加入lombok简化项目-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.14</version>
            <scope>provided</scope>
        </dependency>
package com.xl.xinliao.common.config;

import java.util.*;

import com.xl.xinliao.common.commonEntity.MyShiroRealm;
import com.xl.xinliao.common.listener.ShiroSessionlistener;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        System.out.println("ShiroConfiguration.shirFilter()");
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login/");
        //没有权限跳转的url
        shiroFilterFactoryBean.setUnauthorizedUrl("/login/session");
        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
        // 配置不会被拦截的链接 顺序判断
        /*定义shiro过滤器,例如实现自定义的FormAuthenticationFilter,需要继承FormAuthenticationFilter
         **本例中暂不自定义实现,在下一节实现验证码的例子中体现
         */
        /*HashMap<String, Filter> myFilters = new HashMap<>();
        myFilters.put("authc", new ShiroControListener());
        shiroFilterFactoryBean.setFilters(myFilters);*/

        /*定义shiro过滤链  Map结构
         * Map中key(xml中是指value值)的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的
         * anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种
         * authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter
         */
        filterChainDefinitionMap.put("/css/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/font-awesome/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/fonts/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/js/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/lineicons/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/favicon.con", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/img/**", "anon"); //匿名访问静态资源
        filterChainDefinitionMap.put("/login/login_sysuser", "anon"); //匿名访问静态资源
        // 不需要拦截的访问
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/login/logout", "logout");
        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/**", "authc");

        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        System.out.println("ShiroConfiguration.shirFilter()==");
        return shiroFilterFactoryBean;
    }

    /**
     * 凭证匹配器
     * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
     * )
     * @return
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1024);//散列的次数,比如散列两次,相当于 md5(md5(""));
        //storedCredentialsHexEncoded默认是true,此时用的是密码加密用的是Hex编码;false时用Base64编码
        //hashedCredentialsMatcher.setStoredCredentialsHexEncoded(false);
        return hashedCredentialsMatcher;
    }

    @Bean
    public MyShiroRealm myShiroRealm(){
        MyShiroRealm myShiroRealm = new MyShiroRealm();
        myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        myShiroRealm.setCachingEnabled(true);
        return myShiroRealm;
    }

    @Bean
    public SecurityManager securityManager(){
        DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        ///注入session
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    /**
     *  开启shiro aop注解支持.
     *  使用代理方式;所以需要开启代码支持;
     * @param securityManager
     * @return
     */
    /**
     * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
     * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    @Bean(name="simpleMappingExceptionResolver")
    public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
        SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
        Properties mappings = new Properties();
        mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
        mappings.setProperty("UnauthorizedException","403");
        r.setExceptionMappings(mappings);  // None by default
        r.setDefaultErrorView("error");    // No default
        r.setExceptionAttribute("ex");     // Default is "exception"
        //r.setWarnLogCategory("example.MvcLogger");     // No default
        return r;
    }


    @Bean
    public DefaultWebSessionManager sessionManager(){
        DefaultWebSessionManager sessionManager=new DefaultWebSessionManager();
        // Cookie模板,支持Set注入,用户可以自定义模板
        Cookie cookie = new SimpleCookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
        // 提升Cookie安全性,防止XSS攻击
        cookie.setHttpOnly(true);

        Collection<SessionListener> listeners = new ArrayList<SessionListener>();
        //配置监听
        listeners.add(new ShiroSessionlistener());
        sessionManager.setSessionListeners(listeners);

        //全局会话超时时间(单位毫秒),默认30分钟  暂时设置为10秒钟 用来测试
        sessionManager.setGlobalSessionTimeout(1800000);
        //是否开启删除无效的session对象  默认为true
        sessionManager.setDeleteInvalidSessions(true);
        //是否开启定时调度器进行检测过期session 默认为true
        sessionManager.setSessionValidationSchedulerEnabled(true);
        //设置session失效的扫描时间, 清理用户直接关闭浏览器造成的孤立会话 默认为 1个小时
        //设置该属性 就不需要设置 ExecutorServiceSessionValidationScheduler 底层也是默认自动调用ExecutorServiceSessionValidationScheduler
        //暂时设置为 5秒 用来测试
        sessionManager.setSessionValidationInterval(3600000);
        return sessionManager;
    }






}

package com.xl.xinliao.common.commonEntity;

import com.xl.xinliao.system.entity.SysUser;
import com.xl.xinliao.system.service.ISysRoleService;
import com.xl.xinliao.system.service.ISysUserService;
import org.apache.shiro.authc.*;
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;

public class MyShiroRealm extends AuthorizingRealm {
    @Autowired
    ISysRoleService iSysRoleService;
    @Autowired
    ISysUserService iSysUserService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //获取角色权限
        authorizationInfo.setRoles(iSysRoleService.findRoles(username));
        //获取用户访问路径的权限
        authorizationInfo.setStringPermissions(iSysRoleService.findRolePermissions(username));
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //获取用户的输入的账号.
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();//(String)token.getPrincipal();
        //通过username从数据库中查找 SysUser,如果找到:就验证密码的正确性,没找到:返回空,验证失败
        //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
        SysUser userInfo = iSysUserService.selectInfoName(username);
        if(userInfo == null){
            return null;
        }
        //System .out.println(userInfo.toString());
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //用户实体类
                userInfo.getPassword(),//用户加盐后的密码
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//用户的盐:login_name+salt
                this.getName()  //realm name
        );
        return authenticationInfo;
    }
}

/**
     * 登录接口
     * @param mmap
     * @param sysUser
     * @return
     */
    @RequestMapping("/login_sysuser")//, @PathVariable("id") String id, @RequestParam(value = "name" ,required = false,defaultValue = "0"
    public Object index(ModelMap mmap, SysUser sysUser){
            if (!StringUtils.isEmpty(sysUser)) {
                try {
                    //shiro密码校验
                    Subject currentUser = SecurityUtils.getSubject();
                    UsernamePasswordToken token = new UsernamePasswordToken(sysUser.getLogin_name(), sysUser.getPassword());//sysUser.getPassword());//sh.toString().toCharArray());
                    //token.setRememberMe(false);
                    currentUser.login(token);

                    //查询用户信息
                    SysUser login = iLoginService.selectLogininfor(sysUser);
                    //查询菜单列表
                    List<SysMenu> menus = iSysMenuService.selectInfoJurisdiction(login.getUser_id());
                    mmap.put("user", login);
                    mmap.put("menus", menus);

                    //加入session
                    Session session = SecurityUtils.getSubject().getSession();
                    session.setAttribute("userInfo", login);
                    return "index";
                } catch (Exception E) {
                    //E.printStackTrace();
                    mmap.put("lp", "用户名或密码错误");
                    return "login";
                }
            }
        return "login";
    }
package com.xl.xinliao.system.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

@Data
public class SysUser implements Serializable {
    private Long user_id;//      bigint(20)    用户ID
    private Long dept_id;//      bigint(20)    部门ID
    private String login_name;//   varchar(30)   登录账号
    private String user_name ;//   varchar(30)   用户昵称
    private String user_type;//    varchar(2)    用户类型(00系统用户)
    private String email;//       varchar(50)   用户邮箱
    private String phonenumber;//  varchar(11)   手机号码
    private String sex;//          char(1)       用户性别(0男 1女 2未知)
    private String avatar;//       varchar(100)  头像路径
    private String password;//     varchar(50)   密码
    private String salt;//         varchar(20)   盐加密

    /**
     * 用户盐.
     * @return
     */
    public String getCredentialsSalt(){
        return this.login_name+this.salt;
    }
    //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解

}

实现原理
1.导入相应的pom.xml
2.加入相应的shiro拦截
3.MyShiroRealm 用来登录做校验加密内容
4.然后登录把相应密码传入之后,按照shiro里面的加密规则,与数据库里面加密内容做对比,成功后就会登录成功继续往下走
本节shiro验证我亲测有效。谢谢支持

第一次入住CSDN博客,有什么不懂的可以在下方留言,我看到会对本节内容做详细解决。有什么也可以和我交流

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有规矩不成方圆

你的鼓励是我最大的动力,奥利给

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值