• Springboot项目搭建(4)-shiro登录


    参考:https://www.jianshu.com/p/7f724bec3dc3

    (1)添加依赖

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

    (2)添加用户实体类

    package com.songyan.share.model;
    
    import java.util.Set;
    
    /** 
    * @author songyan
    * @date 2020年3月19日 
    * @desc: 用户
    */
    public class User {
        private String userName;
        private String id;
        private String password;
        private String name;
        private Set<Role> roles;
        
        public User() {
        }
        
        public User(String id, String userName, String password, Set<Role> roles) {
            this.id = id;
            this.userName = userName;
            this.password = password;
            this.roles = roles;
        }
        
        
        public Set<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(Set<Role> roles) {
            this.roles = roles;
        }
    
        public Set<Role> getRoleSet() {
            return roles;
        }
    
        public void setRoleSet(Set<Role> roles) {
            this.roles = roles;
        }
    
        public String getUserName() {
            return userName;
        }
        public void setUserName(String userName) {
            this.userName = userName;
        }
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
    }

    (3)添加角色实体类

    package com.songyan.share.model;
    
    import java.util.Set;
    
    /**
     * @author songyan
     * @date 2020年3月19日
     * @desc: 角色类
     */
    public class Role {
        private String id;
        private String roleName;
        private Set<Permissions> permissions;
    
        public Role(String id, String roleName, Set<Permissions> permissions) {
            this.id = id;
            this.roleName = roleName;
            this.permissions = permissions;
        }
    
        public Role() {
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public Set<Permissions> getPermissions() {
            return permissions;
        }
    
        public void setPermissions(Set<Permissions> permissions) {
            this.permissions = permissions;
        }
    
    }

    (4)添加权限实体类

    package com.songyan.share.model;
    
    /**
     * @author songyan
     * @date 2020年3月19日
     * @desc: 权限类
     */
    public class Permissions {
        private String id;
        private String permissionsName;
        public Permissions() {
        }
        public Permissions(String id, String permissionsName) {
            this.id = id;
            this.permissionsName = permissionsName;
        }
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
        public String getPermissionsName() {
            return permissionsName;
        }
        public void setPermissionsName(String permissionsName) {
            this.permissionsName = permissionsName;
        }
        
    }

    (5)添加登录的service层

    package com.songyan.share.service;
    
    import com.songyan.share.model.User;
    
    /** 
    * @author songyan
    * @date 2020年3月19日 
    * @desc: 
    */
    public interface LoginService {
    
        User getUserByName(String getMapByName); 
    }
    package com.songyan.share.service.impl;
    
    import org.springframework.stereotype.Service;
    
    import com.songyan.share.model.Permissions;
    import com.songyan.share.model.Role;
    import com.songyan.share.model.User;
    import com.songyan.share.service.LoginService;
    
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    /** 
    * @author songyan
    * @date 2020年3月19日 
    * @desc: 
    */
    @Service
    public class LoginServiceImpl implements LoginService {
    
        @Override
        public User getUserByName(String getMapByName) {
            //模拟数据库查询,正常情况此处是从数据库或者缓存查询。
            return getMapByName(getMapByName);
        }
    
        /**
         * 模拟数据库查询
         * @param userName
         * @return
         */
        private User getMapByName(String userName){
            //共添加两个用户,两个用户都是admin一个角色,
            //wsl有query和add权限,zhangsan只有一个query权限
            Permissions permissions1 = new Permissions("1","query");
            Permissions permissions2 = new Permissions("2","add");
            Set<Permissions> permissionsSet = new HashSet<>();
            permissionsSet.add(permissions1);
            permissionsSet.add(permissions2);
            Role role = new Role("1","admin",permissionsSet);
            Set<Role> roleSet = new HashSet<>();
            roleSet.add(role);
            User user = new User("1","wsl","123456",roleSet);
            Map<String ,User> map = new HashMap<>();
            map.put(user.getUserName(), user);
    
            Permissions permissions3 = new Permissions("3","query");
            Set<Permissions> permissionsSet1 = new HashSet<>();
            permissionsSet1.add(permissions3);
            Role role1 = new Role("2","user",permissionsSet1);
            Set<Role> roleSet1 = new HashSet<>();
            roleSet1.add(role1);
            User user1 = new User("2","zhangsan","123456",roleSet1);
            map.put(user1.getUserName(), user1);
            return map.get(userName);
        }
    }

    (6)自定义Realm用于查询用户的角色和权限信息并保存到权限管理器:

    package com.songyan.share.shiro;
    
    import com.songyan.share.model.Permissions;
    import com.songyan.share.model.Role;
    import com.songyan.share.model.User;
    import com.songyan.share.service.LoginService;
    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 org.springframework.beans.factory.annotation.Autowired;
    
    /**
     * @author songyan
     * @date 2020年3月19日
     * @desc:
     */
    public class CustomRealm extends AuthorizingRealm {
    
        @Autowired
        private LoginService loginService;
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            //获取登录用户名
            String name = (String) principalCollection.getPrimaryPrincipal();
            //根据用户名去数据库查询用户信息
            User user = loginService.getUserByName(name);
            //添加角色和权限
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            for (Role role : user.getRoles()) {
                //添加角色
                simpleAuthorizationInfo.addRole(role.getRoleName());
                //添加权限
                for (Permissions permissions : role.getPermissions()) {
                    simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
                }
            }
            return simpleAuthorizationInfo;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
            if (authenticationToken.getPrincipal() == null) {
                return null;
            }
            //获取用户信息
            String name = authenticationToken.getPrincipal().toString();
            User user = loginService.getUserByName(name);
            if (user == null) {
                //这里返回后会报出对应异常
                return null;
            } else {
                //这里验证authenticationToken和simpleAuthenticationInfo的信息
                SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName());
                return simpleAuthenticationInfo;
            }
        }
    }

    (7)把CustomRealm和SecurityManager等加入到spring容器:

    package com.songyan.share.shiro;
    
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import javax.servlet.Filter;
    
    /** 
    * @author songyan
    * @date 2020年3月19日 
    * @desc: 
    */
    @Configuration
    public class ShiroConfig {
        //不加这个注解不生效,具体不详
        @Bean
        @ConditionalOnMissingBean
        public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
            DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
            defaultAAP.setProxyTargetClass(true);
            return defaultAAP;
        }
    
        //将自己的验证方式加入容器
        @Bean
        public CustomRealm myShiroRealm() {
            CustomRealm customRealm = new CustomRealm();
            return customRealm;
        }
    
        //权限管理,配置主要是Realm的管理认证
        @Bean
        public SecurityManager securityManager() {
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(myShiroRealm());
            return securityManager;
        }
    
        @Bean
        public ShiroFilterFactoryBean shiroFilterFactoryBean(org.apache.shiro.mgt.SecurityManager securityManager) {
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);//安全管理器
            Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
            filterChainDefinitionMap.put("/login", "anon");//配置自定义过滤器**
            filterChainDefinitionMap.put("/favicon.ico", "anon");
            filterChainDefinitionMap.put("/css/**", "anon");//静态文件目录
            filterChainDefinitionMap.put("/img/**", "anon");//静态文件目录
            filterChainDefinitionMap.put("/js/**", "anon");//静态文件目录
            filterChainDefinitionMap.put("/plugin/**", "anon");//静态文件目录
            filterChainDefinitionMap.put("/error/**", "anon");
            filterChainDefinitionMap.put("/doLogin/**", "anon");
            filterChainDefinitionMap.put("/logout", "logout");//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
            filterChainDefinitionMap.put("/**", "authc");
            shiroFilterFactoryBean.setLoginUrl("/login");// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
            shiroFilterFactoryBean.setSuccessUrl("/");// 登录成功后要跳转的链接
            shiroFilterFactoryBean.setUnauthorizedUrl("/error/403.html");//未授权界面
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);//路径拦截器.
            return shiroFilterFactoryBean;
        }
    
        //加入注解的使用,不加入这个注解不生效
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
            return authorizationAttributeSourceAdvisor;
        }
    }

    (8)登录控制器

    package com.songyan.share.controller;
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationException;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.apache.shiro.authz.annotation.RequiresRoles;
    import org.apache.shiro.subject.Subject;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.songyan.share.model.ReturnCode;
    import com.songyan.share.model.ReturnObj;
    import com.songyan.share.model.User;
    
    /** 
    * @author songyan
    * @date 2020年3月19日 
    * @desc: 登录
    */
    @RestController
    public class LoginController {
    
         @RequestMapping("/doLogin")
            public Object doLogin(@RequestBody User user) {
                //添加用户认证信息
                Subject subject = SecurityUtils.getSubject();
                UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                        user.getUserName(),
                        user.getPassword()
                );
                try {
                    //进行验证,这里可以捕获异常,然后返回对应信息
                    subject.login(usernamePasswordToken);
    //                subject.checkRole("admin");
    //                subject.checkPermissions("query", "add");
                } catch (AuthenticationException e) {
                    e.printStackTrace();
                    return new ReturnObj("账号或密码错误!",ReturnCode.ERROR_CODE);
                }
                return new ReturnObj("登录成功");
            }
             //注解验角色和权限
            @RequiresRoles("admin")
            @RequiresPermissions("add")
            @RequestMapping("/index")
            public String index() {
                return "index!";
            }
    }

    问题:

    1,请求成功,但是ajax走error:

    原因:ajax中dataType定义了接口返回的类型,所以如果返回的字串就就会走error。

    处理:

      (1)dataType设置为json,后台接口返回一个对象

      (2)dataType设置为text,后台接口返回字符串即可

    2,ajax请求将参数封装成对象传递

    (1)contentType设置为:'application/json'

    (2)后台接口参数前加上注解@RequestBody:  

  • 相关阅读:
    python给邮箱发送消息
    shell 的echo和 printf
    shell 基本运算符
    shell傳遞參數
    shell變量和數組
    pycharm的放大和缩小字体的显示 和ubunt的截圖工具使用 ubuntu上安装qq微信等工具
    flask的g对象
    mysqlcilent的安装
    Ubuntu安装 和 python开发
    使用python来建立http服务
  • 原文地址:https://www.cnblogs.com/excellencesy/p/12081945.html
Copyright © 2020-2023  润新知