参考: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:  

 

 

 

------------------------------------------------------------------------------------------------------补充---------------------------------------------------------------------------------------------------------------------------------------------------------

1,获取当前用户

        Object obj = SecurityUtils.getSubject().getPrincipal();
        User sysUser = (User) obj;

 

2,获取token

SecurityUtils.getSubject().getSession().getId()

 

posted on 2019-12-23 08:14  song.yan  阅读(317)  评论(0)    收藏  举报