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