springmvc+shiro验证嵌入方法介绍,学习笔记(一)

1.添加shiro框架包

<!--shiro权限管理-->
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</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-web</artifactId>
  <version>${shiro.version}</version>
</dependency>
<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-spring</artifactId>
  <version>${shiro.version}</version>
</dependency>

2.在web.xml中添加过滤器,意思是url被该过滤器拦截做权限验证,验证通过才给到controller。
 

<!-- 配置  Shiro 的 Filter -->
<filter>
  <description>shiro 权限拦截</description>
  <filter-name>shiroFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <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>


3.配置shiro的applicationContext
新建一个recources/applicationContext-shiro.xml  (注意按自己的mvc配置命名)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <!-- 启用shrio授权注解拦截方式 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 装配 securityManager -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 配置登陆页面 -->
        <property name="loginUrl" value="/login.html"/>
        <!-- 登陆成功后的一面 -->
        <property name="successUrl" value="/success.html"/>
        <property name="unauthorizedUrl" value="/403.html"/>
        <!-- 具体配置需要拦截哪些 URL, 以及访问对应的 URL 时使用 Shiro 的什么 Filter 进行拦截.  -->
        <property name="filterChainDefinitions">
            <value>
                /login.html = anon
                /subLogin = anon
                /roles = roles[admin]
                /testPerms = roles[admin],perms[ordertable:add]
                /** = roles["admin"]
            </value>
        </property>
    </bean>

    <!-- 配置进行授权和认证的 Realm -->
    <bean id="myRealm" class="cn.longteng.shiro.realm.ShiroDbRealm">
    </bean>

    <!-- 配置 Shiro 的 SecurityManager Bean. -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="myRealm"/>
    </bean>
</beans>

4.自定义Realm,realm时shiro验证身份和权限的逻辑控制器,里面理论上是放账号和权限的数据库查询和判断逻辑
新建一个ShiroDbRealm继承AuthorizingRealm,会要求你重写两个方法
权限授权---doGetAuthorizationInfo(PrincipalCollection principals)
账号认证---doGetAuthenticationInfo(AuthenticationToken token)

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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.HashSet;
import java.util.Set;

/**
 * @Description:
 * @Author longteng
 * @Version v2.0
 * @Date: 2018/9/6
 * @since:
 */
public class ShiroDbRealm extends AuthorizingRealm {
    //授权
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
    {
        System.out.println("数据库进行权限认证");
        //通过传过来的信息中,获取用户名
        String userName = (String) principals.getPrimaryPrincipal();

        //从数据库获取角色与权限
        Set<String> setsR = new HashSet<String>();
        Set<String> setsP = new HashSet<String>();
        getRolesAndPermissionOnDB(userName,setsR,setsP);

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(setsR);;
        simpleAuthorizationInfo.setStringPermissions(setsP);
        return simpleAuthorizationInfo;
    }


    //认证
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
    {
        System.out.println("数据库进行账号认证");
        //通过传过来的信息中,获取用户名
        String userName = (String) token.getPrincipal();

        //通过用户名到数据库中获取凭证
        String password =getPassOnDB(userName);
        if (password == null)
        {
            return null;
        }

        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName, password, "CustomRealm");

        return authenticationInfo;
    }

    private String getPassOnDB(final String username)
    {
        //从数据库里查出密码是多少

        //………………
        return "123456";//假设查出来是123456
    }


    private void getRolesAndPermissionOnDB(String username, Set<String> setsR, Set<String> setsP)
    {
        //从数据库里查出该账号的授权数据

        //…………

        //假设查出来如下
        setsR.add("admin");         //admin角色

        setsP.add("ordertable:add");//权限
        setsP.add("ordertable:del");
    }

}


5.添加以下介个xml用作登陆验证与提示


403.html:

{"ret":"fail","msg":"未经身份验证"}

Success.html:

{"ret":"success","msg":"登陆成功"}

Login.html:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
    <table>登陆</table>
</head>
<body>

    <form action="subLogin" method="post">
        用户名:<input type="text" name="username"><br>
        密码:<input type="text" name="password" ><br>
        <input type="submit" name="登陆">
    </form>
</body>
</html>


Logout.html:

<?xml version="1.0" encoding="UTF-8"?>
<html>
<head>
    <table>是否登出:</table>
</head>
<body>

    <form action="subLogout" method="post">
        <input type="submit" name="登出">
    </form>
</body>
</html>

6.编辑subLogin接口和sunLogout接口
(1)创建类UserController编写接口


 

import cn.longteng.web.comtroller.entity.User;
import cn.longteng.web.utils.RetMsg;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;


/**
 * @Description:
 * @Author longteng
 * @Version v2.0
 * @Date: 2018/9/6
 * @since:
 */
@Controller
public class UserController
{
    @RequestMapping(value = "/subLogin", method = RequestMethod.POST, produces="text/html; charset=UTF-8")
    @ResponseBody
    public String subLogin(User user)
    {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());

        try
        {
            token.setRememberMe(user.isRemenmberMe());

            subject.login(token);
        }
        catch (AuthenticationException e)
        {
            return RetMsg.FL(e.toString());
        }

        return RetMsg.SU("登陆成功");
    }

    @RequestMapping(value = "/subLogout", method = RequestMethod.POST, produces="text/html; charset=UTF-8")
    @ResponseBody
    public String subLogout()
    {
        Subject subject = SecurityUtils.getSubject();

        try
        {

            subject.logout();
        }
        catch (AuthenticationException e)
        {
            return RetMsg.FL(e.toString());
        }

        return RetMsg.SU("登出成功");
    }
}

(2)创建类User类用于参数接收。

public class User
{

    private String username;
    private String password;
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}


7.好了,我们可以开始我们的接口开发了。配合前面的配置

8.我们来测试以下成果
(1)运行起来后你会发现访问任何接口都会跳转到login.html

(2)只有当我们输入账号密码登陆后,接口才能正常调用


(3)接口就可以使用了


9.题外话,如果你做前后端分离的应用,例如为Android的app提供接口,我们怎么进行验证呢?
(1)首先推荐安装一个postman测试工具
(2)按以下配置设置接口

(3)调用成功后查看cookie


(4)配置带该cookie的接口


10.Ok大功告成
当然了,还有MD5密码加密加盐,还有自定义cookie,还有记住验证,还有验证有效期,还有redis的缓存,还有账号比对的优化不要去查那么多次数据。我在后面的的文章给大家介绍。该代码只是shiro结合mvc的原型。还有很多优化和技巧要我们去挖掘,笔者也是才写完一个功能架构,写出这篇文章,大家互相学习,不喜勿喷。(以上代码说明也许有部分遗漏或者错误,如有疑问请下载完整代码)。建议拥有springmvc基础再学习该知识
 

源码地址:https://download.csdn.net/download/c237821375/10664415

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值