精华内容
下载资源
问答
  • Apache Shiro是一个java安全框架。 Shiro可以非常容易开发出足够好的应用,其不仅可以用在JavaSE环境下,也可以用在JavaEE环境下。 Shrio可以完成,认证,授权,加密,会话管理,Web集成,缓存等。 Shiro有哪些功能...


    1. Apache Shiro是一个java安全框架。
    2. Shiro可以非常容易开发出足够好的应用,其不仅可以用在JavaSE环境下,也可以用在JavaEE环境下。
    3. Shrio可以完成,认证,授权,加密,会话管理,Web集成,缓存等。

    Shiro有哪些功能?

    在这里插入图片描述
    Authentication:身份认证/登录,验证用户是不是拥有相应的身份;
    Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
    Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    Web Support:Web支持,可以非常容易的集成到Web环境;
    Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
    Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    Testing:提供测试支持;
    Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
    Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    Shiro 架构

    在这里插入图片描述
    Subject:主体,代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;即一个抽象概念;所有Subject都绑定到SecurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者;
    SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject;可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互,如果学习过SpringMVC,你可以把它看成DispatcherServlet前端控制器;
    Realm:域,Shiro从Realm获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。

    也就是说对于我们而言,最简单的一个Shiro应用:
    1、应用代码通过Subject来进行认证和授权,而Subject又委托给SecurityManager;
    2、我们需要给Shiro的SecurityManager注入Realm,从而让SecurityManager能得到合法的用户及其权限进行判断。

    3.使用

    1. 创建项目 导入pom坐标
    2. 创建shiro.ini
    3. Quickstart 管理打印
    

    学习到里面的方法

    1. 获取当前用户
    Subject currentUser = SecurityUtils.getSubject();
    2. 通过当前用户拿到session值
    Session session = currentUser.getSession();
    3. 判断认证
    currentUser.isAuthenticated()
    4. 获取令牌
    UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
    5. remember Me   
    token.setRememberMe(true);
    6. 获取当前用户的认证
     currentUser.getPrincipal()
    7. 粒度权限
    currentUser.isPermitted("lightsaber:wield")
    currentUser.isPermitted("winnebago:drive:eagle5")
    8. 注销
    currentUser.logout();
    
    展开全文
  • 请问这种情况常用的加密方案有哪些可以参考呢?(别搞成银行那种什么协议之类的,安全性要求没那么高)。 注1:登录进去之后就是winform的外壳,内嵌IE网页,这时候的...
  • shiro框架实战讲解

    2017-09-19 09:12:28
    shiro的权限功能有哪些? 1.身份认证/登录,验证用户是不是拥有相应的身份; 2.授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能事情,常见的如:验证某个用户是否拥有某个角色。或者...

    一、shiro框架介绍

    1.什么是shiro呢?

    shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证、用户授权。

    2.shiro的认证流程


    3.shiro的依赖jar包

    <!-- Spring 整合Shiro需要的依赖 -->  
                <dependency>  
                    <groupId>org.apache.shiro</groupId>  
                    <artifactId>shiro-core</artifactId>  
                    <version>${shiro.version}</version>  
                </dependency>  
                <dependency>  
                    <groupId>org.apache.shiro</groupId>  
                    <artifactId>shiro-web</artifactId>  
                    <version>${shiro.version}</version>  
                </dependency>  
                <dependency>  
                    <groupId>org.apache.shiro</groupId>  
                    <artifactId>shiro-ehcache</artifactId>  
                    <version>${shiro.version}</version>  
                </dependency>  
                <dependency>  
                    <groupId>org.apache.shiro</groupId>  
                    <artifactId>shiro-spring</artifactId>  
                    <version>${shiro.version}</version>  
                </dependency>
            </dependencies>

    4.shiro的权限功能有哪些?

    1.身份认证/登录,验证用户是不是拥有相应的身份;
    2.授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
    3.会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
    4.加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
    5.Web支持,可以非常容易的集成到Web环境;
    Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
    6.shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
    7.记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

    5.什么是权限呢?

    权限管理是系统的安全范畴,要求必须是合法的用户才可以访问系统(用户认证),且必须具有该资源的访问权限才可以访问该资源(授权)。

    二、shiro实例详解

    1.shiro需要依赖的jar包上面已经注上了这里就不再废话了

    2.需要的实体类

    权限类(表),用户类(表),角色类(表),角色用户关联类(表),角色权限关联类(表)

    这几个类与表没什么东西在此就不写了

    3.用户信息类

    public class ActiveUser implements Serializable{
        
        private int userid;//用户id(主键)
        private String usercode;// 用户账号
        private String username;// 用户名称

        private List<Permission> menus;// 菜单
        private List<Permission> permissions;// 权限

    get{},set{}略

    3.自定义的realm

    package com.pment.controller.filter;

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;
    import org.springframework.beans.factory.annotation.Autowired;

    import com.pment.model.ActiveUser;
    import com.pment.model.Permission;
    import com.pment.model.User;
    import com.pment.service.PermissionService;
    import com.pment.service.UserService;


    /**
     * Title: CustomRealm
     * Description:自定义realm
     * @author yuanst
     */
    public class CustomRealm extends AuthorizingRealm {
        
        //注入service
        @Autowired
        private UserService userService;
        
        @Autowired
        private PermissionService permissionService;
        // 设置realm的名称
        @Override
        public void setName(String name) {
            super.setName("customRealm");
        }
        //realm的认证方法,从数据库查询用户信息   登录时验证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken authcToken) throws AuthenticationException {
            
            // token是用户输入的用户名和密码
            // 第一步从token中取出用户名
            UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
            String name=token.getUsername();
            
            // 第二步:根据用户输入的userCode从数据库查询
            User user=null;
            try {
                user = userService.getByName(name);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

            // 如果查询不到返回null
            if(user==null){//
                return null;
            }
            // 从数据库查询到密码
            String password = user.getPassword();
            
        

            // 如果查询到返回认证信息AuthenticationInfo
            
            //activeUser就是用户身份信息
            ActiveUser activeUser = new ActiveUser();
            
            activeUser.setUserid(user.getId());
            activeUser.setUsercode(user.getLoginName());
            activeUser.setUsername(user.getName());
            //..
            
            //根据用户id取出菜单
            List<Permission> permissionList  = null;
            try {
                //通过service取出菜单
                permissionList = permissionService.findMenuListByUserId(user.getId());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //将用户菜单 设置到activeUser
            activeUser.setMenus(permissionList);
            List<String> permissions = new ArrayList<String>();
            if(permissionList!=null){
                for(Permission permission:permissionList){
                    //将数据库中的权限标签 符放入集合
                    permissions.add(permission.getPermissionName());
                }
            }
            this.setSession("USER", user);
            SimpleAuthenticationInfo simpleAuthenticationInfo =  new SimpleAuthenticationInfo(
                    activeUser, password, this.getName());
            
            
            return simpleAuthenticationInfo;
        }

        // 用于授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            
            //从 principals获取主身份信息
            //将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型),
            ActiveUser activeUser =  (ActiveUser) principals.getPrimaryPrincipal();
            
            //根据身份信息获取权限信息
            //从数据库获取到权限数据
            List<Permission> permissionList = null;
            try {
                permissionList = permissionService.findPermissionListByUserId(activeUser.getUserid());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //单独定一个集合对象
            List<String> permissions = new ArrayList<String>();
            if(permissionList!=null){
                for(Permission permission:permissionList){
                    //将数据库中的权限标签 符放入集合
                    permissions.add(permission.getPermissionCode());
                }
            }
            //查到权限数据,返回授权信息(要包括 上边的permissions)
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //将上边查询到授权信息填充到simpleAuthorizationInfo对象中
            simpleAuthorizationInfo.addStringPermissions(permissions);

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

        /**
         * 将一些数据放到ShiroSession中,以便于其它地方使用
         *
         * @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
         */
        private void setSession(Object key, Object value) {
            Subject currentUser = SecurityUtils.getSubject();
            if (null != currentUser) {
                Session session = currentUser.getSession();
                //System.out.println("AuthRealm.setSession():Session默认超时时间为[" + session.getTimeout() + "]毫秒");
                if (null != session) {
                    session.setAttribute(key, value);
                }
            }
        }

        
    }

    4.shiro.xml文件配置


        <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.2.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

    <!-- web.xml中shiro的filter对应的bean -->
    <!-- Shiro 的Web过滤器 -->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <property name="securityManager" ref="securityManager" />
            <!-- loginUrl认证提交地址,如果没有认证将会请求此地址进行认证,请求此地址将由formAuthenticationFilter进行表单认证 -->
            <property name="loginUrl" value="/user/login" />
            <!-- 认证成功统一跳转到此路径,建议不配置,shiro认证成功自动到上一个请求路径 -->
            <!-- <property name="successUrl" value="/user/getAll"/> -->
            <!-- 通过unauthorizedUrl指定没有权限操作时跳转页面-->
            <property name="unauthorizedUrl" value="/index" />
            <!-- 自定义filter配置 -->
     
            <!-- 过虑器链定义,从上向下顺序执行,一般将/**放在最下边 -->
            <property name="filterChainDefinitions">
                <value>
                    <!-- 对静态资源设置匿名访问 -->
                        /resources/**=anon
                    
                        <!-- 退出shiro 自动清除shiro与token shiro自带 不需要写此方法也是可以的 -->
                        /logout = logout
                    <!-- /** = authc 所有url都必须认证通过才可以访问-->
                        /** = authc
                </value>
            </property>
        </bean>

    <!-- securityManager安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="customRealm" />
            <!-- 注入缓存管理器 -->
            <property name="cacheManager" ref="cacheManager"/>
            <!-- 注入session管理器 -->
        <!--     <property name="sessionManager" ref="sessionManager" /> -->
            <!-- 记住我 -->
            <property name="rememberMeManager" ref="rememberMeManager"/>
            
        </bean>

    <!-- realm -->
    <bean id="customRealm" class="com.pment.controller.filter.CustomRealm">
            <property name="authorizationCacheName" value="shiro-authorizationCache"/>  
        <!-- 将凭证匹配器设置到realm中,realm按照凭证匹配器的要求进行散列 -->
        <!--   <property name="credentialsMatcher" ref="credentialsMatcher"/> -->
    </bean>


    <!-- 缓存管理器 -->
     <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
            <property name="cacheManagerConfigFile" value="classpath:ehcache/shiro-ehcache.xml"/>
        </bean>



    <!-- rememberMeManager管理器,写cookie,取出cookie生成用户信息 -->
         <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
            <property name="cookie" ref="rememberMeCookie" />
        </bean>
        <!-- 记住我cookie -->
        <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
            <!-- rememberMe是cookie的名字 -->
            <constructor-arg value="rememberMe" />
        <!--     记住我cookie生效时间30天 -->
            <property name="maxAge" value="2592000" />
        </bean>


    </beans>

    5.缓存配置文件shiro-ehcache.xml

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
        <!--diskStore:缓存数据持久化的目录 地址  -->

        <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
        </defaultCache>
    </ehcache>
    此就只是将用户已验证过的信息存入到缓存中

    6.web.xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="taotao" version="2.5">
        <display-name>pment-manger</display-name>
        <welcome-file-list>
            <welcome-file>index.html</welcome-file>
            <welcome-file>index.htm</welcome-file>
            <welcome-file>index.jsp</welcome-file>
            <welcome-file>default.html</welcome-file>
            <welcome-file>default.htm</welcome-file>
            <welcome-file>default.jsp</welcome-file>
        </welcome-file-list>
    <!-- 加载spring容器 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/applicationContext-*.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <filter>  
            <filter-name>sitemesh</filter-name>  
            <filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>  
        </filter>  
          
          <!-- shiro 代理过滤器 -->
        <filter>
            <filter-name>shiroFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
            <!-- 设置true由servlet容器控制filter的生命周期 -->
            <init-param>
                <param-name>targetFilterLifecycle</param-name>
                <param-value>true</param-value>
            </init-param>
            <!-- 设置spring容器filter的bean id,如果不设置则找与filter-name一致的bean-->
             <init-param>
                <param-name>targetBeanName</param-name>
                <param-value>shiroFilter</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>shiroFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        
        <filter-mapping>  
            <filter-name>sitemesh</filter-name>  
            <url-pattern>/*</url-pattern>  
        </filter-mapping>  
        <!-- 解决post乱码 -->
        <filter>
            <filter-name>CharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>utf-8</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

        
        <servlet>
            <servlet-name>pment-manger</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" -->
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/springmvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!-- 加载静态资源 -->
        <servlet-mapping>
            <servlet-name>default</servlet-name>
            <url-pattern>*.js</url-pattern>
            <url-pattern>*.css</url-pattern>
            <url-pattern>/resources/*</url-pattern>
        </servlet-mapping>
        <servlet-mapping>
            <servlet-name>pment-manger</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    </web-app>

    7.controller代码

    package com.pment.controller;

    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Enumeration;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.ExcessiveAttemptsException;
    import org.apache.shiro.authc.IncorrectCredentialsException;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.subject.Subject;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;

    import com.alibaba.fastjson.JSON;
    import com.pment.common.util.MD5Utils;
    import com.pment.model.Record;
    import com.pment.model.User;
    import com.pment.service.RecordService;
    import com.pment.service.UserService;
    import com.pment.vo.UserVo;


    @Controller
    @RequestMapping("user")
    public class UserController extends BaseController{
        
        /**
         * 日志记录器
         */
        private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
        
        @Autowired
        private UserService userService;
        
        @Autowired
        private RecordService recordService;
        
        @RequestMapping("/login")
        public String login(HttpServletRequest request) throws Exception{
            String name=request.getParameter("username");   //前台页面获取的用户名称
            String password=request.getParameter("password");    //前台用户输入的密码
            String passwordMD5=MD5Utils.encryptByMD5(password); // 将用户输入的密码加密(这是我自己写的MD5加密,需要根据自己的情况加密与否)
            UsernamePasswordToken token = new UsernamePasswordToken(name, passwordMD5);
                Subject subject = SecurityUtils.getSubject();  
                try {
                    subject.login(token); // 将用户提交到realm进行验证
                } catch(UnknownAccountException uae){  
                    SecurityUtils.getSubject().logout(); // 此处是进行用户登录将错误的信息token清除以下雷同
                    LOGGER.warn("对用户[" + name + "]进行登录验证..验证未通过,未知账户");
                    request.getSession().setAttribute("message_login", "未知账户");  
                }catch(IncorrectCredentialsException ice){  
                    SecurityUtils.getSubject().logout();
                    LOGGER.warn("对用户[" + name + "]进行登录验证..验证未通过,错误的凭证");
                    request.getSession().setAttribute("message_login", "密码不正确");  
                }catch(ExcessiveAttemptsException eae){  
                    SecurityUtils.getSubject().logout();
                    LOGGER.warn("对用户[" + name + "]进行登录验证..验证未通过,错误次数过多");
                    
                    request.getSession().setAttribute("message_login", "用户名或密码错误次数过多");  
                }catch(AuthenticationException ae){  
                    //通过处理Shiro的运行时AuthenticationException就可以控制用户登录失败或密码错误时的情景  
                    LOGGER.warn("对用户[" + name + "]进行登录验证..验证未通过,堆栈轨迹如下");
                    ae.printStackTrace();  
                    request.getSession().setAttribute("message_login", "用户名或密码不正确");  
                }  
                if(subject.isAuthenticated()){  
                    System.out.println("认证通过");
                    return "redirect:/user/getAll"; //这里我写的是登录后固定进入此页面而不是进入刷新时的页面(因为我不知道如何进入刷新时的那个页面)
                }else{  
                    token.clear();
                    return "login"; //登录错误返回登录页面
                }  
        }
        
        @RequestMapping("/getAll")
        public String getAll(HttpServletRequest request)
        {
            //用于获取session中用户的信息
            User user=(User) request.getSession().getAttribute("USER");
            String type=request.getParameter("listtype");
            Map map=new HashMap();
            /**
             * 用于获取所有值
             */
            Enumeration enu=request.getParameterNames();
            /**
             * 解析接收的值并放入map中
             */
            List<Record> list=null;
            while(enu.hasMoreElements())
            {  
                String paraName=(String)enu.nextElement();  
                map.put(paraName, request.getParameter(paraName));
            }
            
            Map<String, Object> chartData = new HashMap<String, Object>();
        
                 list=recordService.getAll(map);
            
            List<String> proname=new ArrayList<String>();
            List<Integer> inok=new ArrayList<Integer>();
            List<Integer> innotok=new ArrayList<Integer>();
            List<Integer> count=new ArrayList<Integer>();
            
            if(list.size() > 0)
            {
                for (int i = 0; i < list.size(); i++)
                {
                    
                        proname.add(list.get(i).getProjectname());
                
                    if(list.get(i).getResult()!=null){
                        if(list.get(i).getResult() == 0)
                        {
                            inok.add(list.get(i).getCount());
                        }
                        else if(list.get(i).getResult() == 1)
                        {
                            innotok.add(list.get(i).getCount());
                        }
                    }
                }
                if (inok.size()>0) {
                    for (int i = 0; i < inok.size(); i++) {
                        count.add(inok.get(i)+innotok.get(i));
                    }
                }
            }
            /**
             * proname 去除重复项目
             */
            Set set=new HashSet();
            List listpro=new ArrayList();
            for (String name:proname) {
                if(set.add(name)){
                    listpro.add(name);
                }
                
            }
        /*    HashSet h = new HashSet(proname);      
            proname.clear();      
            proname.addAll(h);  */
            chartData.put("count", count);
            chartData.put("proname", listpro);
            chartData.put("inok", inok);
            chartData.put("notok", innotok);
            List<Record> records =recordService.listPro();
            String data=JSON.toJSONString(chartData);
            request.setAttribute("data",data);
            request.setAttribute("map", map);
            request.setAttribute("records", records);
            return "record/chart";
        }
        
      
    }

    8.login.jsp页面

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding="utf-8"%>
          <%@include file="/WEB-INF/view/common.jsp" %>
        
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>shiro</title>

    <style>
    body{ width:100vw; height:100vh; background:url(${static_common}/images/login-bg.png) no-repeat center #08213f ; padding:18vh 0}
    </style>
    </head>
    <body>
     
           
             <div class="Login">    
         
                <form action="${ctx}/user/login" method="post">
                  <div class="form-group">
                   <label >
                     <span>用户名:</span>
                     <input type="text" name="username"/>
                   </label>
                  </div>
                  <div class="form-group">
                   <label>
                     <span >密码:</span>
                     <input type="password" name="password"/>
                   </label>
                   <span id="userspan"></span>
                  </div>
                  <div class="form-group">
                   <label>
                     <button>登录</button>
                   </label>
                  </div>
                </form>
             </div>
        
       
            <script type="text/javascript">
                var data=${data};
                if(data=="nameerror"){
                    $("#userspan").text("用户名不可用");
                }else if(data=="passerror"){
                    $("#userspan").text("密码错误");
                }
                    
            
            </script>
    </body>
    </html>

    9.登录成功

        <shiro:hasPermission name="YHGL">
                                <li><a href="${ctx}/user/list">用户管理</a></li>
                            </shiro:hasPermission>
             登录成功后就可以根据权限名称判断用户是否有此权限

    三、总结

    在搭建shiro框架的时候一定要了解shiro的原理以及它的实现机制,不然在搭建过程中遇到的问题解决都不知道从何下手去解决。我在此分享一下我在搭建shiro的过程中遇到的问题 (1)刚开始我是在网上搜索了一个项目代码复制过来就开跑,于是启动项目就报错提示什么tokenException,session异常等等,项目报错了怎么办?怎么解决呢?这些问题我在开发过程中从未遇到过只能网上查,有的说什么seesion过期,token失效,还有的说jar包版本不对,因此我整整看了一周左右没有解决问题。于是自己从新看实现原理,终于发现自己的配置文件多了session的会话配置  <!--  <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
            <property name="globalSessionTimeout" value="1800000"/>
            <property name="deleteInvalidSessions" value="true"/>
            <property name="sessionValidationSchedulerEnabled" value="true"/>

            <property name="sessionIdCookieEnabled" value="true"/>  
            <property name="sessionIdCookie" ref="sessionIdCookie"/>  
        </bean>

        <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
            <constructor-arg name="name" value="meta.session.id"/>
        </bean> -->但是我并没有对此配置做任何处理于是就报错了注释掉可以正常启动了

    (2)开始登陆又报错了,用户名密码错误,我密码都是加密后去验证的怎么还会报错呢?看数据库密码与提交密码在看配置

    <!-- 凭证匹配器 -->
    <!--  <bean id="credentialsMatcher"
        class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
        <property name="hashAlgorithmName" value="md5" />
        <property name="hashIterations" value="1" />
    </bean>  -->我这是用于加密提交后的密码的,后来我直接提交1去验证还是登录失败,不管是加密还是不加密都是报错,干脆注释掉,注释掉可以登录,虽然问题解决了

    但是你不知道为何,于是又研究,在一篇博客中看到数据库有一个自带的md5加密和我自己写的MD5不一样又学会了一招

    (3)登录成功了。(4)退出:登录可以了下一步肯定是退出,但是退出又出问题了,我同事说没有清除session用户,当时由于自己不懂就remove.session清除,但是并没有任何效果,同事说是用户登录的时候seesion就没有存进去,又搞了几天没有搞懂,接着回去看原理了发现和什么session没有任何关系,只是需要登录提交token 退出清理token即可。明白了原理机制,我没有写退出方法也实现了退出登录<property name="filterChainDefinitions">
                <value>
                    <!-- 对静态资源设置匿名访问 -->
                        /resources/**=anon
                        <!-- /timerController/**=anon -->
                        <!-- 退出shiro 自动清除shiro与token shiro自带 不需要写此方法也是可以的 -->
                        /logout = logout
                    <!-- /** = authc 所有url都必须认证通过才可以访问-->
                        /** = authc
                </value>
            </property>

     终上所述:在搭建框架的时候一定要看看实现原理以免走错方向带来不必要的时间浪费。



    展开全文
  • #{}和${}的区别是什么 #{}是预编译处理,${}是字符串替换。 Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法...都有哪些动态sql?能简述一下动态sql的执行原理不? Mybatis动态sql可以

    #{}和${}的区别是什么

    #{}是预编译处理,${}是字符串替换。

    Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

    Mybatis在处理{}时,就是把{}替换成变量的值。

    使用#{}可以有效的防止SQL注入,提高系统安全性。
    一般能用#的就别用$
    $方式一般用于传入数据库对象,例如传入表名.

    Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

    Mybatis动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能,Mybatis提供了9种动态sql标签trim|where|set|foreach|if|choose|when|otherwise|bind。

    其执行原理为,使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。

    Mybatis是否支持延迟加载?如果支持,它的实现原理是什么

    Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

    它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

    Mybatis的一级、二级缓存

    1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

    2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;

    3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

    展开全文
  • 另一个目的则是看看大厂的 app 到底用了哪些第三方工具,在技术选型时也可以作为参考。 但是由于对第三方 SDK 的依赖和混淆技术、加固等安全技术可能存在不准确的情况,后续会继续优化。下面是使用频率最高的 10 ...

    这两天学了一门新语言———— Python 并使用 Python 抓取了应用市场大厂的部分 app 。有两个目的,一个目的练习一下 Python 。另一个目的则是看看大厂的 app 到底用了哪些第三方工具,在做技术选型时也可以作为参考。

    但是由于对第三方 SDK 的依赖和混淆技术、加固等安全技术可能存在不准确的情况,后续会继续优化。下面是使用频率最高的 10 个开源项目。

    okhttp

    okhttp 最初是由 Square 开源的 http 框架,支持 Http / Http 2.0。Google 在 Android 6.0 移除了 HttpClient,okhttp 是目前 Android 开发中最常用的网络请求框架。

    项目地址:github.com/square/okht…

    Gson

    Gson 是由 Google 开源的将 JSON 与 Java 对象互相转换的协议,使用非常加单。

    项目地址:github.com/google/gson

    Glide

    Glide 是一个快速高效的图片加载框架。功能强大、API 易用、容易扩展。

    项目地址:github.com/bumptech/gl…

    material-components-android

    material-components-android 是一个 MD 风格的 UI 组件库。Material Design 是 Android 的主流设计风格,越来越多的 APP 遵循 Material Design 的设计规范,是每个 Android 开发者都必学的基础技术。

    项目地址:github.com/material-co…

    zxing

    zxing 是 Android 开发中的二维码扫描库,可见扫一扫功能几乎是 app 标配了。

    项目地址:github.com/zxing/zxing

    Tinker

    Tinker 是微信团队开源的 Android 客户端热修复框架,使用简单、性能高、稳定。

    项目地址:github.com/Tencent/tin…

    lottie-android

    lottie-android 是 Airbnb 开源的动画框架,江湖传言有了这个框架再复杂的动画都会变得简单。

    项目地址:github.com/airbnb/lott…

    AndroidHttpClient

    AndroidHttpClient 是一个网络请求框架。可能是由于历史原因很多项目不能直接将其剔除。

    项目地址:loopj.com/android-asy…

    Fresco

    Fresco 是由 Facebook 开发的高性能的图片加载框架,支持 4.x 以上的系统,但是使用了它之后应用程序的包会大约 7+ M。

    项目地址:github.com/facebook/fr…

    thrift & protobuf

    thrift 是一款软件开发RPC框架,可以很高效地实现跨语言的RPC服务。protobuf 是一种轻便高效的结构化数据存储格式,平台无关、语言无关、可扩展,可用于通讯协议和数据存储等领域。

    项目地址:github.com/apache/thri…

    项目地址:github.com/google/prot…


    微信号:「chqing-dev」

    分享大前端技术、关注职场发展和行业动态。

    活好、长得帅的都扫了下方的二维码了。

    转载于:https://juejin.im/post/5c6b64776fb9a04a0b22bcba

    展开全文
  • 安全级别就是:如果一个节点里面没有设置可以访问哪些字段,那么就默认为不需要做到控制字段的程度,就是说节点里的字段都是可以访问的。这么是为了操作方便。2、高安全级别。有些项目要求非常严格,要严...
  • AOP的主要功能日志记录、性能统计、安全控制、事务处理和异常处理 核心概念: Spring AOP就像一把刀,在代码的执行的过程中,可以随意的插入和拔出。在插入和拔出的位置可以“任意妄为”的自己喜欢的事。 ...
  • 5、通过智能设备上的 UART 接口一般我们可以做哪些事情? 查看设备调试信息 获取设备权限 6、以下关于进程、线程、协程的的说法正确的是? 线程是堆共享,栈私有 一般而言,执行开销进程 >
  • 因此 KCP 的方式是把协议栈 “拆开”,让大家可以根据项目需求进行灵活的调整和组装,你可以下面加一层 reed solomon 的纠删码 FEC,上面加一层类 RC4/Salsa20 流加密,握手处再设计一套非对称密钥交换,底层 ...
  • Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会一个相对应...
  • 108.spring boot 有哪些方式可以实现热部署? 109.jpa 和 hibernate 有什么区别? 110.什么是 spring cloud? 111.spring cloud 断路器的作用是什么? 112.spring cloud 的核心组件有哪些? 十二、Hibernate 113.为...
  • 后台使用Spring+Hibernate,前端使用dwr或者...我的问题关键是框架只使用HTML+ajax+Spring+Hibernate,是否有成功案例,以及这样有哪些缺陷? 谢谢jasongreen的回答!到时如果没有更好的,我一定把分给你。
  • 阿里 菜鸟网络(一面)

    2021-06-03 21:21:14
    介绍一下你的项目,用了哪些模块?技术细节可以介绍一下。 web框架是什么? SpringBoot和Spring的区别?什么优势? Java中常用的数据结构?这些数据结构是线程安全的吗? 如果我要在多线程的环境下使用这些数据...
  • Xss相关的没有安全方面的处理。 输入URL到渲染的全部过程。 二面 框架方面 大文件上传断点续传的问题; 介绍项目顶目中没有什么觉得自己的还不错的东西; react hooks 使用的注意事项; react 如何提升性能...
  • 反勒索编程实战篇

    千人学习 2019-07-16 17:02:10
    我对必题也进行了“爱”设计,它可以确保一个事情:如果你得出来,就代表你一定看懂了整体框架和运作流程。不出来那一定是没看懂!不会存在看懂了但不出来,或者出来了但没看懂的情况。作业的设计,本身也...
  • 这种功能对于安全测试是非常有用的,当然也可以用来一般的功能测试,因为所有的代码路径都可以用来演习。 通过显示所有的Http通讯,Fiddler可以轻松地演示哪些用来生成一个页面,通过统计页面(就是Fiddler左边的...
  • 前后端分离后提供的 REST 接口应该如何做安全校验? Vue.js 和 Node.js 在异步回调这块什么好的方案? 没有用过 OpenResty?和 Node 的差别是什么?值不值得学? 作为前端开发人员,如果想进行后端开发,需要...
  • 1.2.6 一颗现代处理器,每秒大概可以执行多少条简单的MOV指令,有哪些主要的影响因素 1.2.7 请分析 MaxCompute 产品与分布式技术的关系、当前大数据计算平台类产品的市场现状和发展趋势 1.2.8 对大数据平台中的...
  • fiddler 天涯浪子

    2014-05-24 23:39:21
    这种功能对于安全测试是非常有用的,当然也可以用来一般的功能测试,因为所有的代码路径都可以用来演习。 通过显示所有的Http通讯,Fiddler可以轻松地演示哪些用来生成一个页面,通过统计页面(就是Fiddler左边的...
  • 类hackernews源码iNews.zip

    2019-07-16 07:59:16
    iNews 有哪些创新性的东西? 赵戈戈:如果说创新的话,我想提一个设计模式:MOVE。应该有不少人看到过过这个设计模式,摒弃了MVC传统老套的做法。采用了Model、Operator、View 和 Event 来梳理编码流程。其中 ...
  • e销存云平台

    2013-06-13 09:59:46
    e销存云平台有哪些优点? 1.基于云端服务平台,实时的权限控制、数据DES加密传,私有协议传输,数据安全且不会丢失; 2.下载安装APP到android(2.1以上)手机,即可体验使用或注册自己的商户号使用,操作方便,易学...
  • 程序员可以选择哪些平台写技术博客? IDEA使用总结 Maven就是这么简单 敖丙这逼竟然连Maven都不会 SVN就是这么简单 UML就是这么简单 听说新版IDEA支持中文,三歪体验了一把 加入公众号 精美脑图、学习路线、1000+...
  • 因此,您可以在一个安全的地方使文件可供包成员使用。 动态内容,可通过Django的内置管理框架进行管理。 为什么要使用这个应用程序? Packman是专门为管理Cub Scout Pack 144编写的,该软件包位于华盛顿州西雅图...
  • 熔断框架有哪些?具体实现原理知道吗? 熔断框架如何技术选型?选用 Sentinel 还是 Hystrix? 降级 如何进行降级? 微服务架构 微服务架构整个章节内容属额外新增,后续抽空更新,也欢迎读者们参与补充...
  • PHP168建站系统

    2010-06-01 15:51:35
    可以很方便的采集类似奇虎这样的新闻,也就是说你可以做一个像奇虎这样的站。 D、强大的数据库备份功能  1.可以指定备份站外或站内的数据,站内指本CMS系统。当然也可以指定备份哪些数据表的数据。 2.强大的分卷...

空空如也

空空如也

1 2 3 4 5 6
收藏数 113
精华内容 45
关键字:

有哪些安全框架可以做