shiro登录认证 与授权

shiro配置文件

<!-- 以下都是Apache安全框架Shiro的配置 -->
    <!-- 数据库保存的密码是使用MD5算法加密的,所以这里需要配置一个密码匹配对象 -->
    <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.Md5CredentialsMatcher"></bean>
    <!-- 缓存管理 ,第一次 会去数据库中取权限,后面就从缓存中取 -->
    <bean id="shiroCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean>
   <!-- 自定义realm -->  
    <bean id="customRealm" class="com.ecenter.sso.security.CustomRealm">  
        <!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->  
       <property name="credentialsMatcher" ref="credentialsMatcher" />
    </bean>
    <!-- Shiro安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="customRealm" />
        <property name="cacheManager" ref="shiroCacheManager" />
        <property name="sessionManager" ref="sessionManager"/>
    </bean>
 <aop:config proxy-target-class="true"></aop:config>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
        <property name="securityManager" ref="securityManager"/>
    </bean>
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--Shiro的核心安全接口,这个属性是必须的-->
        <property name="securityManager" ref="securityManager"></property>
        <!--要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面-->
        <property name="loginUrl" value="/login"></property>
        <!--登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码)-->
        <!--<property name="successUrl" value="/"></property>-->
        <!--用户访问未对其授权的资源时,所显示的连接-->
        <property name="unauthorizedUrl" value="/noPower.jsp"></property>
        <property name="filterChainDefinitions">
            <value>
                /checkCode/getCodeImage=anon
                /login=anon
                /userInfo/edit=anon
                /userInfo/password=anon
                /userInfo/passwordChange=anon                
                /doLogin=anon
                /lib/**=anon
                /**=authc
            </value>
        </property>
    </bean>

前端登录请求

        $.ajax({
                    type : "POST",
                    url : "/doLogin",
                    data : $('#form').serialize(),
                    error : function(request) {
                        alert("操作失败!");
                    },
                    success : function(data) {
                        if (data == '200') {
                            if ($('#remember-password').attr('checked')) {
                                var cookie = new rememberPassword();
                                cookie.cookieRemeber();
                            }
                            window.location.href = "/index";
                        } else if (data == '500') {
                            $('#password').val('');
                            $('#checkCode').val('');
                            $('#checkCode').attr('placeholder','');
                            changeImg();
                            $('#password').attr('placeholder','用户名或密码不正确');
                            $('#password').focus();
                        } else if (data == '401') {
                            $('#checkCode').val('');
                            $('#checkCode').attr('placeholder','验证码不正确');
                            changeImg();
                        }else if(data == '501'){
                            layui.use(['laypage', 'layer'], function(){
                                var laypage = layui.laypage
                                    ,layer = layui.layer;
                                layer.open({
                                      type: 2, //类型,解析url
                                      closeBtn: 1, //关闭按钮是否显示 1显示0不显示
                                      title: '密码修改', //页面标题
                                      shadeClose: true, //点击遮罩区域是否关闭页面
                                      shade: 0.3,  //遮罩透明度
                                      area: ['650px', '300px'],  //弹出层页面比例
                                      content: '/userInfo/password'  //弹出层的url
                                  });

                            });
                        }else {
                            if(data == '10'){
                                $('#username').val('');
                                $('#checkCode').val('');
                                $('#password').val('');
                                $('#username').attr('placeholder','用户已删除,无法登陆');

                            }else if(data == '11'){
                                $('#username').val('');
                                $('#checkCode').val('');
                                $('#password').val('');
                                $('#username').attr('placeholder','用户暂未通过审核');
                            }else if(data == '12'){
                                $('#username').val('');
                                $('#checkCode').val('');
                                $('#password').val('');
                                $('#username').attr('placeholder','用户未能通过审核');
                            }else if(data == '14'){
                                $('#username').val('');
                                $('#checkCode').val('');
                                $('#password').val('');
                                $('#username').attr('placeholder','用户已被禁用');
                            }else if(data == '3'){
                                $('#username').val('');
                                $('#checkCode').val('');
                                $('#password').val('');
                                $('#username').attr('placeholder','用户已被禁用');
                            }
                        }
                    }
                });

后端登录接口  /dologin

   @RequestMapping("/doLogin")
    @ResponseBody
    public String doLogin(HttpServletRequest request,
            HttpServletResponse response,
            @RequestParam("username") String username,
            @RequestParam("password") String password,
            @RequestParam("checkCode") String checkCode) {

        if (!checkCode.equalsIgnoreCase((String) request.getSession().getAttribute("code"))) {
            return Constant.RES_CHECKCODE_ERROR; // 验证码不正确
        }
        UsernamePasswordToken token = new UsernamePasswordToken(username,password, true);
        Subject subject = SecurityUtils.getSubject();
        try {
            subject.login(token);
            List<Session> loginedList = getLoginedSession(subject);
            for (Session session : loginedList) {
                session.stop();
            }
            Session session = subject.getSession();
            if (subject.isAuthenticated()) {
                Map<String, Object> claims = new HashMap<String, Object>();
                User user = iUserService.findByUsername(username);
                claims.put("username", username);
                claims.put("usertype", user.getUsertype());
                claims.put("areaCode", user.getAreacode());
                if("123456".equals(password)){
                    session.setAttribute("username", username);
                    return Constant.PASSWORD_EASY;//密码太简单
                }
                // 验证成功后 使用JWT生成加密的token
                String JWT = JavaWebToken.createJavaWebToken(claims);
                session.setAttribute("Authorization", JWT);
                session.setAttribute("areaCode", user.getAreacode());
                session.setAttribute("usersession", user);
                return Constant.RES_SUCCESS;
            } else {
                return Constant.RES_FAIL;
            }
        } catch (IncorrectCredentialsException e) {// 登录密码错误
            return Constant.RES_FAIL;
        } catch (ExcessiveAttemptsException e) { // 登录失败次数过多
            return Constant.RES_FAIL;
        } catch (UnknownAccountException e) { // 帐号不存在
            return Constant.RES_FAIL;
        }
    }
subject.login(token);源码追踪

 

 

 

 

 

 

 

 

 

 

 

 

 

 

自定义的 Realm 对象

package com.ecenter.sso.security;
public class CustomRealm extends AuthorizingRealm {
    @Autowired
    private IUserService iUserService;
    @Autowired(required=true)
    private SessionDAO sessionDAO;
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // token中包含用户输入的用户名和密码
        // 第一步从token中取出用户名
        String userName = (String) token.getPrincipal();
        // 第二步:根据用户输入的userCode从数据库查询
        User user = iUserService.findByUsername((String) token.getPrincipal());
        // 如果查询不到返回null
        if (user == null) {//
            return null;
        }
        // 获取数据库中的密码
        String password = user.getPassword();
         //认证的用户,正确的密码
        AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(userName, password, this.getName());
        Session currentSession = null;
        Collection<Session> sessions = sessionDAO.getActiveSessions();
/*        for(Session session:sessions){
            if(userName.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)))) {
                //session.setTimeout(0);//设置session立即失效,即将其踢出系统
                session.stop();
                break;
            }
        }*/

        return authcInfo;
    }

    /**
     * 授权,只有成功通过<span style="font-family: Arial, Helvetica, sans-serif;">
     * doGetAuthenticationInfo方法的认证后才会执行。</span>
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        // 从 principals获取主身份信息
        // 将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
        String username = (String) principals.getPrimaryPrincipal();
        // 根据身份信息获取权限信息
        // 从数据库获取到权限数据
        // 单独定一个集合对象
        ArrayList<String> permissions = (ArrayList<String>) iUserService.getUserPermission(username);

        // 查到权限数据,返回授权信息(要包括 上边的permissions)
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        // 将上边查询到授权信息填充到simpleAuthorizationInfo对象中
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    // 清除缓存
    public void clearCached() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }
}

 

 

 

 

posted @ 2020-04-08 16:09  java小白百百  阅读(505)  评论(0编辑  收藏  举报