zoukankan      html  css  js  c++  java
  • Shiro身份认证、盐加密

    目的:

      Shiro认证

      盐加密工具类


    Shiro认证

      1.导入pom依赖

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.3.2</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-web</artifactId>
        <version>1.3.2</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-spring</artifactId>
        <version>1.3.2</version>
    </dependency>

      2.web.xml

    <!-- shiro过滤器定义 -->
    <filter>
      <filter-name>shiroFilter</filter-name>
      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      <init-param>
        <!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
      </init-param>
    </filter>
    <filter-mapping>
      <filter-name>shiroFilter</filter-name>
      <url-pattern>/*</url-pattern>
    </filter-mapping>

     设置五个表并且用逆向生成相应的mapper

    generatorConfig.xml
     <table schema="" tableName="t_shiro_permission" domainObjectName="ShiroPermission"
                   enableCountByExample="false" enableDeleteByExample="false"
                   enableSelectByExample="false" enableUpdateByExample="false">
            </table>
            <table schema="" tableName="t_shiro_role" domainObjectName="ShiroRole"
                   enableCountByExample="false" enableDeleteByExample="false"
                   enableSelectByExample="false" enableUpdateByExample="false">
            </table>
    
            <table schema="" tableName="t_shiro_role_permission" domainObjectName="ShiroRolePermission"
                   enableCountByExample="false" enableDeleteByExample="false"
                   enableSelectByExample="false" enableUpdateByExample="false">
            </table>
            <table schema="" tableName="t_shiro_user" domainObjectName="ShiroUser"
                   enableCountByExample="false" enableDeleteByExample="false"
                   enableSelectByExample="false" enableUpdateByExample="false">
            </table>
    
            <table schema="" tableName="t_shiro_user_role" domainObjectName="ShiroUserRole"
                   enableCountByExample="false" enableDeleteByExample="false"
                   enableSelectByExample="false" enableUpdateByExample="false">
            </table>

     

     ShiroUserMapper

    @Repository
    public interface ShiroUserMapper {
        int deleteByPrimaryKey(Integer userid);
    
        int insert(ShiroUser record);
    
        int insertSelective(ShiroUser record);
    
        ShiroUser selectByPrimaryKey(Integer userid);
    
        int updateByPrimaryKeySelective(ShiroUser record);
    
        int updateByPrimaryKey(ShiroUser record);
    
        ShiroUser queryByName(String userName);
    }

    ShiroUserMapper.xml

    <select id="queryByName" resultType="com.huangting.model.ShiroUser" parameterType="java.lang.String">
        select
        <include refid="Base_Column_List" />
        from t_shiro_user
        where username = #{username}
      </select>
    ShiroUserService
    /**
     * @author 黄大娘
     * @company dogsun
     * @oreata 2019-10-13 20:19
     */
    public interface ShiroUserService{
        /**
         * 用于认证的
         * @param userName
         * @return
         */
        public ShiroUser queryByName(String userName);
    
        /**
         * 注册
         * @param shiroUser
         * @return
         */
        int insert(ShiroUser shiroUser);
    }
    ShiroUserServiceImpl
    /**
     * @author 黄大娘
     * @company dogsun
     * @oreata 2019-10-13 20:23
     */
    @Service("shiroUserService")
    public class ShiroUserServiceImpl implements ShiroUserService {
        @Autowired
        private ShiroUserMapper shiroUserMapper;
        @Override
        public ShiroUser queryByName(String userName) {
            return shiroUserMapper.queryByName(userName);
        }
        @Override
        public int insert(ShiroUser shiroUser) {
            return shiroUserMapper.insert(shiroUser);
        }
    }
    MyRealm
    对新建方法获取的用户信息进行认证
    /**
     * @author 黄大娘
     * @company dogsun
     * @oreata 2019-10-13 19:54
     * 认证的过程:
     * 1、数据源(ini=>数据库)
     * 2、doGetAuthenticationInfo将数据库的用户信息给subject主体做shiro认证的
     *      2.1、需要在当前realm中调用service来验证,判断当前用户是否在数据库中存在
     *      2.2、盐加密
     */
    public class MyRealm extends AuthorizingRealm {
        private ShiroUserService shiroUserService;
    
        public ShiroUserService getShiroUserService() {
            return shiroUserService;
        }
    
        public void setShiroUserService(ShiroUserService shiroUserService) {
            this.shiroUserService = shiroUserService;
        }
        /**
         * 授权
         * @param principalCollection
         * @return
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    
        /**
         * 认证
         * 此方法认证数据源
         * @param token    从jsp传递过来的用户名密码组成成的一个token对象
         * @return
         * @throws AuthenticationException
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            String userName = token.getPrincipal().toString();
            String pwd = token.getCredentials().toString();
            ShiroUser shiroUser = this.shiroUserService.queryByName(userName);
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                    shiroUser.getUsername(),
                    shiroUser.getPassword(),
                    ByteSource.Util.bytes(shiroUser.getSalt()),
                    this.getName()
            );
            return info;
        }
    }
    applicationContext-shiro.xml
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--配置自定义的Realm-->
        <bean id="shiroRealm" class="com.huangting.shrio.MyRealm">
            <property name="shiroUserService" ref="shiroUserService" />
            <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
            <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
            <!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 -->
            <!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密-->
            <property name="credentialsMatcher">
                <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                    <!--指定hash算法为MD5-->
                    <property name="hashAlgorithmName" value="md5"/>
                    <!--指定散列次数为1024次-->
                    <property name="hashIterations" value="1024"/>
                    <!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储-->
                    <property name="storedCredentialsHexEncoded" value="true"/>
                </bean>
            </property>
        </bean>
    
        <!--注册安全管理器-->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
            <property name="realm" ref="shiroRealm" />
        </bean>
    
        <!--Shiro核心过滤器-->
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
            <!-- Shiro的核心安全接口,这个属性是必须的 -->
            <property name="securityManager" ref="securityManager" />
            <!-- 身份验证失败,跳转到登录页面 -->
            <property name="loginUrl" value="/login"/>
            <!-- 身份验证成功,跳转到指定页面 -->
            <!--<property name="successUrl" value="/index.jsp"/>-->
            <!-- 权限验证失败,跳转到指定页面 -->
            <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
            <!-- Shiro连接约束配置,即过滤链的定义 -->
            <property name="filterChainDefinitions">
                <value>
                    <!--
                    注:anon,authcBasic,auchc,user是认证过滤器
                        perms,roles,ssl,rest,port是授权过滤器
                    -->
                    <!--anon 表示匿名访问,不需要认证以及授权-->
                    <!--authc表示需要认证 没有进行身份认证是不能进行访问的-->
                    <!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->
                    /user/login=anon
                    /user/updatePwd.jsp=authc
                    /admin/*.jsp=roles[admin]
                    /user/teacher.jsp=perms["user:update"]
                   <!-- /css/**               = anon
                    /images/**            = anon
                    /js/**                = anon
                    /                     = anon
                    /user/logout          = logout
                    /user/**              = anon
                    /userInfo/**          = authc
                    /dict/**              = authc
                    /console/**           = roles[admin]
                    /**                   = anon-->
                </value>
            </property>
        </bean>
    
        <!-- Shiro生命周期,保证实现了Shiro内部lifecycle函数的bean执行 -->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    </beans>
    ShiroUserController
    /**
     * @author 黄大娘
     * @company dogsun
     * @oreata 2019-10-14 21:28
     */
    @Controller
    public class ShiroUserController {
        @Autowired
        private ShiroUserService shiroUserService;
    
        @RequestMapping("/login")
        public String login(HttpServletRequest req, HttpServletResponse resp){
            Subject subject = SecurityUtils.getSubject();
            String uname = req.getParameter("username");
            String pwd = req.getParameter("password");
            UsernamePasswordToken token = new UsernamePasswordToken(uname,pwd);
            try {
                subject.login(token);
                return "main";
            }catch (Exception e){
                req.setAttribute("message","用户名或者密码错误!!!");
                return "login";
            }
        }
    
        @RequestMapping("/logout")
        public String logout(HttpServletRequest req, HttpServletResponse resp){
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
    
            return "login";
        }
    
        @RequestMapping("/register")
        public String register(HttpServletRequest req, HttpServletResponse resp){
            String uname = req.getParameter("username");
            String pwd = req.getParameter("password");
            String salt = PasswordHelper.createSalt();
            String credentials = PasswordHelper.createCredentials(pwd, salt);
    
            ShiroUser shiroUser=new ShiroUser();
            shiroUser.setUsername(uname);
            shiroUser.setPassword(credentials);
            shiroUser.setSalt(salt);
            int insert = shiroUserService.insert(shiroUser);
            if(insert>0){
                req.setAttribute("message","注册成功!!!");
                return "login";
            }
            else{
                req.setAttribute("message","注册失败!!!");
                return "login";
            }
        }
    }

    login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>用户登陆</h1>
    <div style="color: red">${message}</div>
    <form action="${pageContext.request.contextPath}/login" method="post">
        帐号:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="确定">
        <input type="button" onclick="location.href='${pageContext.request.contextPath}/register.jsp'" value="注册">
        <input type="reset" value="重置">
    </form>
    </body>
    </html>
    register.jsp
    <%--
      Created by IntelliJ IDEA.
      User: Administrator
      Date: 2019/10/14
      Time: 21:33
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>用户注册</title>
    </head>
    <body>
    <h1>用户注册</h1>
    <form action="${pageContext.request.contextPath}/register" method="post">
        帐号:<input type="text" name="username"><br>
        密码:<input type="password" name="password"><br>
        <input type="submit" value="注册">
        <input type="button" onclick="location.href='login.jsp'" value="返回">
    </form>
    
    </body>
    </html>
    
    

    盐加密工具类

      PasswordHelper工具类

    import org.apache.shiro.crypto.RandomNumberGenerator;
    import org.apache.shiro.crypto.SecureRandomNumberGenerator;
    import org.apache.shiro.crypto.hash.SimpleHash;
    
    /**
     * 用于shiro权限认证的密码工具类
     */
    public class PasswordHelper {
    
        /**
         * 随机数生成器
         */
        private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
    
        /**
         * 指定hash算法为MD5
         */
        private static final String hashAlgorithmName = "md5";
    
        /**
         * 指定散列次数为1024次,即加密1024次
         */
        private static final int hashIterations = 1024;
    
        /**
         * true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储
         */
        private static final boolean storedCredentialsHexEncoded = true;
    
        /**
         * 获得加密用的盐
         *
         * @return
         */
        public static String createSalt() {
            return randomNumberGenerator.nextBytes().toHex();
        }
    
        /**
         * 获得加密后的凭证
         *
         * @param credentials 凭证(即密码)
         * @param salt        盐
         * @return
         */
        public static String createCredentials(String credentials, String salt) {
            SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,
                    salt, hashIterations);
            return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();
        }
    
    
        /**
         * 进行密码验证
         *
         * @param credentials        未加密的密码
         * @param salt               盐
         * @param encryptCredentials 加密后的密码
         * @return
         */
        public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {
            return encryptCredentials.equals(createCredentials(credentials, salt));
        }
    
        public static void main(String[] args) {
            //
            String salt = createSalt();
            System.out.println(salt);
            System.out.println(salt.length());
            //凭证+盐加密后得到的密码
            String credentials = createCredentials("123456", salt);
            System.out.println(credentials);
            System.out.println(credentials.length());
            boolean b = checkCredentials("123456", salt, credentials);
            System.out.println(b);
        }
    }

    谢谢观看!

  • 相关阅读:
    【实用】网站常用单词的中英文对照表
    [译][转]jQuery 1.4 发布:15个新特性实例精讲
    popupWindow 简单实现
    程序员修炼之道 读书笔记
    Burp Suite详细使用教程Intruder模块详解
    漏洞挖掘练习环境(linux方向)
    linux系统操作常见问题(ubuntu和opensuse)
    驱动的加载顺序
    磁盘驱动相关知识
    VS 驱动工程创建软件(EeasySyS)
  • 原文地址:https://www.cnblogs.com/huangting/p/11674804.html
Copyright © 2011-2022 走看看