springboot集成Shiro完成登录权限功能

Shiro有三个主题,Subject,安全管理器,Realm域;

subject:存储登录名/邮箱/手机号等主体标识和密码;
安全管理器:与subject交互
realm域:一般自定义,复写登录方法和授权方法

建表语句:
CREATE TABLE zz_user (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(255) DEFAULT NULL,
password varchar(255) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE zz_role (
role_id int(11) NOT NULL AUTO_INCREMENT,
role_name varchar(255) DEFAULT NULL,
user_id int(11) DEFAULT NULL,
PRIMARY KEY (role_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE zz_permission (
permission_id int(11) NOT NULL AUTO_INCREMENT,
permission_name varchar(255) DEFAULT NULL,
role_id int(11) DEFAULT NULL,
PRIMARY KEY (permission_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

依赖:

<dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>RELEASE</version>
      </dependency>

自定义Realm域

//自定义Realm继承并复写其登录,权限操作
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private ShiroMapper shiroMapper;
    @Override
    //权限认证,即登录过后,每个身份不一定,对应的所能看的页面也不一样。
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取主体标识
        String username = (String) principalCollection.getPrimaryPrincipal();
        //用AuthorizationInfo接口实现
        AuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
        //设置角色
        Set<String> roles= shiroMapper.selectRolesByUser(username);
        ((SimpleAuthorizationInfo) authorizationInfo).setRoles(roles);
        //设置权限
        Set<String> permissions=shiroMapper.selectPermissionsByUser(username);
        ((SimpleAuthorizationInfo) authorizationInfo).setStringPermissions(permissions);
        return authorizationInfo;
    }



    @Override
    //身份认证。即登录通过账号和密码验证登陆人的身份信息。
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //根据token获取接口传入的用户名和密码
        String username = (String) authenticationToken.getPrincipal();
        String credentials = (String) authenticationToken.getCredentials();
        //MD5加密(盐为当前用户名+666)
        String inputPassword = MD5Util.encryptPassword(username, credentials, username+666);
        //获取正确的密码
        String password = (String) shiroMapper.selectUserByUsernameAndPassword(username).get("password");
        if(inputPassword.equals(password)){
            Map<String, Object> map=new HashMap<>();
            map.put("username",username);
            map.put("password",password);
            //登陆成功,存进session
            SecurityUtils.getSubject().getSession().setAttribute("user",map);
            //返回
            AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(username,password,"MyRealm");
            return authenticationInfo;
        }
        return null;
    }

bean注入

   @Bean
    public MyRealm myRealm(){
        return new MyRealm();
    }
    @Bean
    public SecurityManager securityManager(){
        //web应用使用DefaultWebSecurityManager
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(myRealm());
        return defaultWebSecurityManager;
    }

配置shiro过滤器

public class ShiroConfig {

    /**
     * 注入 Shiro 过滤器
     * @param securityManager 安全管理器
     * @return ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
        // 定义 shiroFactoryBean
        ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();

        // 设置自定义的 securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        // 设置默认登录的 URL,身份认证失败会访问该 URL
        shiroFilterFactoryBean.setLoginUrl("/login");
        // 设置成功之后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/success");
        // 设置未授权界面,权限认证失败会访问该 URL
        shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

        // LinkedHashMap 是有序的,进行顺序拦截器配置
        Map<String,String> filterChainMap = new LinkedHashMap<>();

        // 配置可以匿名访问的地址,可以根据实际情况自己添加,放行一些静态资源等,anon 表示放行
        filterChainMap.put("/css/**", "anon");
        filterChainMap.put("/imgs/**", "anon");
        filterChainMap.put("/js/**", "anon");
        filterChainMap.put("/swagger-*/**", "anon");
        filterChainMap.put("/swagger-ui.html/**", "anon");
        // 登录 URL 放行
        filterChainMap.put("/login", "anon");

        // 以“/user/admin” 开头的用户需要身份认证,authc 表示要进行身份认证
        filterChainMap.put("/user/admin*", "authc");
        ///user/student” 开头的用户需要角色认证,是“admin”才允许
        filterChainMap.put("/user/student*/**", "roles[admin]");
        // “/user/teacher” 开头的用户需要权限认证,是“user:create”才允许
        filterChainMap.put("/user/teacher*/**", "perms[\"user:create\"]");

        // 配置 logout 过滤器
        filterChainMap.put("/logout", "logout");

        // 设置 shiroFilterFactoryBean 的 FilterChainDefinitionMap
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
        log.info("====shiroFilterFactoryBean注册完成====");
        return shiroFilterFactoryBean;
    }
@RequestMapping(value = "/login")
@Slf4j
public class ShiroController {
    @RequestMapping(method = RequestMethod.GET,value = "/{username}/{password}")
    public Integer shiro(@PathVariable String username,@PathVariable String password) {
        // 从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        //MD5加密(盐为当前用户名+666)
        String s = MD5Util.encryptPassword(username, password, username + 666);
        // 在认证提交前准备 token(令牌)
        AuthenticationToken token=new UsernamePasswordToken(username,s);
        try {
            //登录
            subject.login(token);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
            return 2;
        }

    }
  }

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>商铺订单管理网站</title>
    <style>
        *all{
            margin: 0;
            padding: 0;
        }
        div.inner,table{
            position:absolute;
        }
        body{
            background-image:url(aaa.jpg);
            background-size:100%;
        }
        .outer{
            height: 100%;
        }
        .inner{
            border: 5px solid rgba(255,255,255,1);
            border-radius: 20px;
            width: 370px;
            height: 340px;
            top: 40%;
            left: 76%;
            transform: translate(-50%,-50%);
            box-shadow:11px 11px 11px rgba(50,50,50,1);	///边框阴影
        }
        .table{
            top: 7%;
            left: 12%;
        //border: solid;
            width: 260px;
            height: 190px;
            border-spacing:7px;
        }
        .under{
            position: fixed;
            left: 0px;
            bottom: 30px;
            width: 100%;
            text-align:center;
            font-size: 15px;
        }
        .Time{
            top: 65%;
            left: 62%;
            position: fixed;
            width: 400px;
            text-align:right;
        }
        .TEXT{
            height:72%;
            width: 200px;
        }
        a {text-decoration: none}
    </style>
</head>
<body>
<div class="outer">
    <div id="showInfo"></div>
    <div class="inner">
        <table class="table">
            <caption> <h1>订单管理系统</h1> </caption>
            <tr height="30px">
                <td><big><b>&nbsp;&nbsp;</b></big></td>
                <td><input type="text" name="username" id="username"class="TEXT"/> </td>
            </tr>
            <tr height="30px">
                <td><big><b>&nbsp;&nbsp;</b></big></td>
                <td><input class="TEXT"type="password" name="password" id="password"/> </td>
            </tr>
            <tr height="30px">
                <td colspan="2" align="right">
                    <input class="TEXT" type='button' id="login"  value="            登陆系统              "/>
                    <script><!--检查用户名 密码-->
                    </script>
                </td>
            </tr>
            <tr height="20px"><td colspan="2" style="text-align:right;font-size:small"><a href = "">联系我们</a> | <a href = "">帮助中心</a> | <a href = "">其他</a></td></tr>
        </table>
    </div>
    <script type="text/javascript">
        window.onload = function(){
            var btn = document.getElementById('login');
            btn.onclick  = function(){
                var username = document.getElementById('username').value;
                var password = document.getElementById('password').value;
                //第一步:创建对象
                var xhr = null;
                if(window.XMLHttpRequest){
                    xhr = new XMLHttpRequest();
                }else{
                    xhr = new ActiveXObject("Microsoft.XMLHTTP");
                }
                //初始化
                //准备好了
                var url = './login/'+username+"/"+password;
                xhr.open('get',url,false);

                //这段代码在xhr.send();执行完之后才能执行
                //这件事做完了怎么办
                //事情办完之后干什么
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        if(xhr.status == 200){
                            var data = xhr.responseText;
                            if(data == 2){
                                window.location.replace("error.html")
                            }else if(data == 1){
                                window.location.replace("success.html")
                            }
                        }
                    };
                }
                //实际的去做这件事
                //去做这件事情
                xhr.send(null);
            }
        }

    </script>

    <div class="under"><span>显示器分辨率要求≥1024*768,请使用Firefox浏览器(<a href="http://www.firefox.com.cn/" target="_blank">官网下载</a>),可以获得最佳显示效果,Chrome浏览器次之,IE浏览器则要求10或以上版本,其他浏览器较慢且有卡顿等现象。</span></div>
</div>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值