用到的框架技术有:springboot、mybatis、shiro、redis
前端有:layui、jqGrid
这里先不讲redis在Windows安装,比较简单,百度看一下其他文章就可以了,有空这里也可以补一个教程。
实体类,权限PermissionEntity.java
package com.xiaostudy.shiro_test1.entity;
import java.io.Serializable;
/**
* 权限实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:21
* Description: No Description
*/
public class PermissionEntity implements Serializable {
private String id;
private String name;
private String url;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
实体类,角色RoleEntity.java
package com.xiaostudy.shiro_test1.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* 角色实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:24
* Description: No Description
*/
public class RoleEntity implements Serializable {
private String id;
private String name;
private Set
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<PermissionEntity> getPermissions() {
return permissions;
}
public void setPermissions(Set<PermissionEntity> permissions) {
this.permissions = permissions;
}
}
实体类,用户UserEntity.java
package com.xiaostudy.shiro_test1.entity;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
/**
* 用户实体类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:26
* Description: No Description
*/
public class UserEntity implements Serializable {
private String id;
private String name;
private String password;
private Set
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Set<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Set<RoleEntity> roles) {
this.roles = roles;
}
}
实体类,测试redis实体类TestRedisEntity.java
package com.xiaostudy.shiro_test1.entity;
import java.io.Serializable;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 22:04
* Description: No Description
*/
public class TestRedisEntity implements Serializable {
private int id;
private String name;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
自定义Realm类,UserRealm.java
package com.xiaostudy.shiro_test1.realm;
import com.xiaostudy.shiro_test1.entity.PermissionEntity;
import com.xiaostudy.shiro_test1.entity.RoleEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
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.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
/**
* 自定义Realm,实现授权与认证
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:01
* Description: No Description
*/
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/\*\*
\* 用户授权
\*\*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principalCollection) {
System.out.println("===执行授权===");
Subject subject = SecurityUtils.getSubject();
UserEntity user = (UserEntity)subject.getPrincipal();
if(user != null){
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 角色字符串集合
Collection<String> rolesCollection = new HashSet<>();
// 权限字符串集合
Collection<String> premissionCollection = new HashSet<>();
// 读取并赋值用户角色与权限
Set<RoleEntity> roles = user.getRoles();
for(RoleEntity role : roles){
rolesCollection.add(role.getName());
Set<PermissionEntity> permissions = role.getPermissions();
for (PermissionEntity permission : permissions){
// 权限名称为PermissionEntity为字段url
premissionCollection.add(permission.getUrl());
}
info.addStringPermissions(premissionCollection);
}
info.addRoles(rolesCollection);
return info;
}
return null;
}
/\*\*
\* 用户认证
\*\*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("===执行认证===");
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
UserEntity bean = userService.findByName(token.getUsername());
if(bean == null){
// 用户不存在
throw new UnknownAccountException();
} else {
bean = userService.findById(bean.getId());
if(null == bean) {
// 认证失败
throw new AuthenticationException();
}
}
ByteSource credentialsSalt = ByteSource.Util.bytes(bean.getName());
return new SimpleAuthenticationInfo(bean, bean.getPassword(),
credentialsSalt, getName());
}
}
处理没权限异常,NoPermissionException.java
package com.xiaostudy.shiro_test1.exception;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:13
* Description: No Description
*/
@ControllerAdvice
public class NoPermissionException {
// 授权失败,就是说没有该权限
@ExceptionHandler(UnauthorizedException.class)
public String handleShiroException(Exception ex) {
return "/error/unAuth";
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String AuthorizationException(Exception ex) {
return "权限认证失败";
}
}
shiro配置类,ShiroConfig.java
package com.xiaostudy.shiro_test1.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import com.xiaostudy.shiro_test1.realm.UserRealm;
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.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Shiro配置类
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:06
* Description: No Description
*/
@Configuration
public class ShiroConfig {
// 创建自定义 realm
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
// 创建 SecurityManager 对象
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm());
return securityManager;
}
// Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
/\*\*
\* anon:匿名用户可访问
\* authc:认证用户可访问
\* user:使用rememberMe可访问
\* perms:对应权限可访问
\* role:对应角色权限可访问
\*/
LinkedHashMap<String, String> map = new LinkedHashMap<>();
// map.put("/resources/**", "anon");//匿名访问静态资源
map.put("/static/**", "anon");//匿名访问静态资源
map.put("/statics/**", "anon");//匿名访问静态资源
map.put("/jquery.jqGrid-4.6.0/**", "anon");//匿名访问静态资源
map.put("/jquery-ui-1.12.0-rc.2/**", "anon");//匿名访问静态资源
map.put("/layui/**", "anon");//匿名访问静态资源
map.put("/external/**", "anon");//匿名访问静态资源
map.put("/jquery/**", "anon");//匿名访问静态资源
map.put("/js/**", "anon");//匿名访问静态资源
map.put("/css/**", "anon");//匿名访问静态资源
map.put("/images/**", "anon");//匿名访问静态资源
// 开放登录接口
map.put("/login", "anon");
// map.put("/login", "authc");
// 对登录跳转接口进行释放
map.put("/error", "anon");
// 对所有用户认证
map.put("/**", "authc");
// 登出
map.put("/logout", "logout");
// 登录
// 注意:这里配置的 /login 是指到 @RequestMapping(value="/login")中的 /login
shiroFilterFactoryBean.setLoginUrl("/login");
// 首页
shiroFilterFactoryBean.setSuccessUrl("/index");
// 错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/error/unAuth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
// 加入注解的使用,不加这个,注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
// 跟上面的注解配置搭配使用,有时候加了上面的配置后注解不生效,需要加入下面的配置
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator();
app.setProxyTargetClass(true);
return app;
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
静态资源过滤配置类【告诉shiro不要拦截】,WebMvcConfig.java
package com.xiaostudy.shiro_test1.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/9
* Time: 0:51
* Description: No Description
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
/\*\*
\* @author xiaobu
\* @date 2019/1/18 13:51
\* @param registry registry
\* @descprition 等价于 http://localhost:9001/1.txt 依次在static upload目录下找1.txt文件
\* @version 1.0
\*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/\*\*").addResourceLocations("classpath:/static/");
registry.addResourceHandler("/static/\*\*").addResourceLocations("classpath:/static/");
}
}
用户mapper,UserMapper.xml
<resultMap id="userMap" type="com.xiaostudy.shiro\_test1.entity.UserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="password" column="password"/>
<collection property="roles" ofType="com.xiaostudy.shiro\_test1.entity.RoleEntity">
<id property="id" column="roleId"/>
<result property="name" column="roleName"/>
<collection property="permissions" ofType="com.xiaostudy.shiro\_test1.entity.PermissionEntity">
<id property="id" column="permissionId"/>
<result property="name" column="permissionName"/>
<result property="url" column="permissionUrl"/>
</collection>
</collection>
</resultMap>
<select id="findByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro\_test1.entity.UserEntity">
SELECT id, name, password
FROM user
WHERE name = #{name}
</select>
<select id="findById" parameterType="java.lang.String" resultMap="userMap">
SELECT user.id, user.name, user.password,
role.id as roleId, role.name as roleName,
permission.id as permissionId,
permission.name as permissionName,
permission.url as permissionUrl
FROM user, user\_role, role, role\_permission, permission
WHERE user.id = #{id}
AND user.id = user\_role.user\_id
AND user\_role.role\_id = role.id
AND role.id = role\_permission.role\_id
AND role\_permission.permission\_id = permission.id
</select>
测试redis的mapper,TestRedisMapper.xml
<select id="selectAll" resultType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity" >
SELECT id, name, password
FROM test\_redis;
</select>
<select id="selectPages" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity" >
SELECT id, name, password
FROM test\_redis limit #{page}, #{rows};
</select>
<select id="selectTotal" resultType="java.lang.Integer" >
SELECT COUNT(\*) as total FROM test\_redis;
</select>
<select id="selectById" parameterType="java.lang.Integer" resultType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity">
SELECT id, name, password
FROM test\_redis
WHERE id = #{id};
</select>
<select id="selectByName" parameterType="java.lang.String" resultType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity">
SELECT id, name, password
FROM test\_redis
WHERE name = #{name};
</select>
<insert id="insert" parameterType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity" >
insert into test\_redis (name, password) value (#{name}, #{password});
</insert>
<update id="update" parameterType="com.xiaostudy.shiro\_test1.entity.TestRedisEntity" >
update test\_redis
set
name = #{name},
password = #{password}
where
id = #{id};
</update>
<delete id="deleteById" parameterType="java.lang.Integer" >
delete from test\_redis
where
id = #{id};
</delete>
<delete id="deleteByName" parameterType="java.lang.String" >
delete from test\_redis
where
name = #{name};
</delete>
用户mapper,UserMapper.java
package com.xiaostudy.shiro_test1.mapper;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import org.apache.ibatis.annotations.Mapper;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:45
* Description: No Description
*/
@Mapper
public interface UserMapper {
// 根据用户名称,查询用户信息
public UserEntity findByName(String name);
// 根据用户id,查询用户信息、角色、权限
public UserEntity findById(String id);
}
测试redis的mapper,TestRedisMapper.java
package com.xiaostudy.shiro_test1.mapper;
import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 22:07
* Description: No Description
*/
@Mapper
public interface TestRedisMapper {
public List<TestRedisEntity> selectAll();
/\*\*
\* 简单分页
\* <p>@Param的作用是告诉mapper他的参数名,因为存在多个参数</p>
\* @param page
\* @param rows
\* @return
\*/
public List<TestRedisEntity> selectPages(@Param("page") int page, @Param("rows") int rows);
public int selectTotal();
public TestRedisEntity selectById(int id);
public TestRedisEntity selectByName(String name);
public int insert(TestRedisEntity testRedisEntity);
public int update(TestRedisEntity testRedisEntity);
public int deleteById(int id);
public int deleteByName(String name);
}
用户service,UserService.java
package com.xiaostudy.shiro_test1.service;
import com.xiaostudy.shiro_test1.entity.UserEntity;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:55
* Description: No Description
*/
public interface UserService {
UserEntity findByName(String name);
UserEntity findById(String id);
}
测试redis的service,TestRedisService.java
package com.xiaostudy.shiro_test1.service;
import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:55
* Description: No Description
*/
public interface TestRedisService {
public List<TestRedisEntity> selectAll();
public List<TestRedisEntity> selectPages(int page, int rows);
public int selectTotal();
public TestRedisEntity selectById(int id);
public TestRedisEntity selectByName(String name);
public int insert(TestRedisEntity testRedisEntity);
public int update(TestRedisEntity testRedisEntity);
public int deleteById(int id);
public int deleteByName(String name);
}
用户service实现类,UserServiceImpl.java
package com.xiaostudy.shiro_test1.service.impl;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.mapper.UserMapper;
import com.xiaostudy.shiro_test1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:56
* Description: No Description
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public UserEntity findByName(String name) {
return userMapper.findByName(name);
}
@Override
public UserEntity findById(String id) {
return userMapper.findById(id);
}
}
测试redis的service实现类,TestRedisServiceImpl.java
package com.xiaostudy.shiro_test1.service.impl;
import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.mapper.TestRedisMapper;
import com.xiaostudy.shiro_test1.mapper.UserMapper;
import com.xiaostudy.shiro_test1.service.TestRedisService;
import com.xiaostudy.shiro_test1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 14:56
* Description: No Description
*/
@Service
public class TestRedisServiceImpl implements TestRedisService {
@Autowired
private TestRedisMapper testRedisMapper;
@Autowired
private RedisTemplate<Object,Object> redisTemplate;
@Override
public List<TestRedisEntity> selectAll() {
List<TestRedisEntity> redisEntityList = (List<TestRedisEntity>) redisTemplate.opsForValue().get("testRedisAll");
if(null == redisEntityList) {
redisEntityList = testRedisMapper.selectAll();
redisTemplate.opsForValue().set("testRedisAll", redisEntityList);
}
return redisEntityList;
}
@Override
public List<TestRedisEntity> selectPages(int page, int rows) {
int current = (page-1)\*rows;
List<TestRedisEntity> redisEntityList = (List<TestRedisEntity>) redisTemplate.opsForValue().get("testRedisByPages\_page" + page + "\_rows" + rows);
if(null == redisEntityList) {
redisEntityList = testRedisMapper.selectPages(current, rows);
redisTemplate.opsForValue().set("testRedisByPages\_page" + page + "\_rows" + rows, redisEntityList);
}
return redisEntityList;
}
@Override
public int selectTotal() {
String strTotal = (String) redisTemplate.opsForValue().get("testRedisTotal");
int total;
if(null == strTotal) {
total = testRedisMapper.selectTotal();
redisTemplate.opsForValue().set("testRedisTotal",String.valueOf(total));
} else {
total = Integer.parseInt(strTotal);
}
return total;
}
@Override
public TestRedisEntity selectById(int id) {
TestRedisEntity testRedisEntity = (TestRedisEntity) redisTemplate.opsForValue().get("testRedisById\_" + id);
if(null == testRedisEntity) {
testRedisEntity = testRedisMapper.selectById(id);
redisTemplate.opsForValue().set("testRedisById\_" + id, testRedisEntity);
}
return testRedisEntity;
}
@Override
public TestRedisEntity selectByName(String name) {
TestRedisEntity testRedisEntity = (TestRedisEntity) redisTemplate.opsForValue().get("testRedisByName\_" + name);
if(null == testRedisEntity) {
testRedisEntity = testRedisMapper.selectByName(name);
redisTemplate.opsForValue().set("testRedisByName\_" + name, testRedisEntity);
}
return testRedisEntity;
}
@Override
public int insert(TestRedisEntity testRedisEntity) {
int insert = testRedisMapper.insert(testRedisEntity);
this.closeRedis(insert, "testRedisByPages");
redisTemplate.opsForValue().set("testRedisTotal",String.valueOf(testRedisMapper.selectTotal()));
return insert;
}
@Override
public int update(TestRedisEntity testRedisEntity) {
int update = testRedisMapper.update(testRedisEntity);
this.closeRedis(update, "testRedisByPages");
redisTemplate.opsForValue().set("testRedisById\_" + testRedisEntity.getId(), testRedisEntity);
redisTemplate.opsForValue().set("testRedisByName\_" + testRedisEntity.getName(), testRedisEntity);
return update;
}
@Override
public int deleteById(int id) {
TestRedisEntity testRedisEntity = this.selectById(id);
int deleteById = testRedisMapper.deleteById(id);
this.closeRedis(deleteById, "testRedisByPages");
this.closeRedis(deleteById, "testRedisTotal");
this.closeRedis(deleteById, "testRedisById\_" + id);
this.closeRedis(deleteById, "testRedisByName\_" + testRedisEntity.getName());
return deleteById;
}
@Override
public int deleteByName(String name) {
TestRedisEntity testRedisEntity1 = this.selectByName(name);
int deleteByName = testRedisMapper.deleteByName(name);
this.closeRedis(deleteByName, "testRedisByPages");
this.closeRedis(deleteByName, "testRedisTotal");
this.closeRedis(deleteByName, "testRedisByName\_" + name);
this.closeRedis(deleteByName, "testRedisById\_" + testRedisEntity1.getId());
return deleteByName;
}
/\*\*
\* 清空对应实体的缓存
\* @param count
\*/
private void closeRedis(int count, String str) {
if(0 != count) {
redisTemplate.delete(redisTemplate.keys(str + "\*"));
}
}
}
用户登录controller,MainController.java
package com.xiaostudy.shiro_test1.web.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 用户登录、登出、错误页面跳转控制器
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:15
* Description: No Description
*/
@Controller
public class MainController {
@RequestMapping("/index")
public String index(HttpServletRequest request, HttpServletResponse response){
response.setHeader("root", request.getContextPath());
return "index";
}
@RequestMapping("/login")
public String login(HttpServletRequest request, HttpServletResponse response){
response.setHeader("root", request.getContextPath());
String userName = request.getParameter("username");
String password = request.getParameter("password");
// 等于null说明用户没有登录,只是拦截所有请求到这里,那就直接让用户去登录页面,就不认证了。
// 如果这里不处理,那个会返回用户名不存在,逻辑上不合理,用户还没登录怎么就用户名不存在?
if(null == userName) {
return "login";
}
// 1.获取Subject
Subject subject = SecurityUtils.getSubject();
// 2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
// 3.执行登录方法
try{
subject.login(token);
return "redirect:/index";
} catch (UnknownAccountException e){
// 这里是捕获自定义Realm的用户名不存在异常
request.setAttribute("msg","用户名不存在!");
} catch (IncorrectCredentialsException e){
request.setAttribute("userName",userName);
request.setAttribute("msg","密码错误!");
} catch (AuthenticationException e) {
// 这里是捕获自定义Realm的认证失败异常
request.setAttribute("msg","认证失败!");
}
return "login";
}
@RequestMapping("/logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
subject.logout();
}
// return "redirect:/main";
return "login";
}
@RequestMapping("/error/unAuth")
public String unAuth(){
return "/error/unAuth";
}
@RequestMapping("/err")
public String err(){
return "/error/unAuth";
}
}
用户权限controller,UserController.java
package com.xiaostudy.shiro_test1.web.controller;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
/**
* 用户页面跳转
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:21
* Description: No Description
*/
@Controller
public class UserController {
/\*\*
\* 个人中心,需认证可访问
\*/
@RequestMapping("/user/index")
@RequiresPermissions(value = "user")// 这里的user,就是对应权限实体类PermissionEntity的字段url,自定义Realm类UserRealm里是用这个字段
public String add(HttpServletRequest request){
UserEntity bean = (UserEntity) SecurityUtils.getSubject().getPrincipal();
request.setAttribute("userName", bean.getName());
return "/user/index";
}
/\*\*
\* 会员中心,需认证且角色为vip可访问
\*/
@RequestMapping("/vip/index")
@RequiresPermissions(value = "vip")
public String update(){
return "/vip/index";
}
}
测试redis的controller,TestRedisController.java
package com.xiaostudy.shiro_test1.web.controller;
import com.xiaostudy.shiro_test1.entity.TestRedisEntity;
import com.xiaostudy.shiro_test1.entity.UserEntity;
import com.xiaostudy.shiro_test1.service.TestRedisService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 用户页面跳转
* Created with IntelliJ IDEA.
* User: Administrator
* Date: 2019/6/8
* Time: 15:21
* Description: No Description
*/
@Controller
@RequestMapping("/testRedis")
public class TestRedisController {
@Autowired
private TestRedisService testRedisService;
@RequestMapping("/index")
public String index() {
return "testRedis/index";
}
@RequestMapping("/all")
@ResponseBody
public Map getTestRedisAll() {
List<TestRedisEntity> redisEntityList = testRedisService.selectAll();
Map map = new HashMap();
map.put("redisEntityList", redisEntityList);
return map;
}
@RequestMapping("/pages")
@ResponseBody
public Map getTestRedisPages(String page, String rows) {
List<TestRedisEntity> redisEntityList = testRedisService.selectPages(Integer.parseInt(page), Integer.parseInt(rows));
int total = testRedisService.selectTotal();
Map map = new HashMap();
map.put("redisEntityList", redisEntityList);
map.put("pages", total/Integer.parseInt(rows)+((total%Integer.parseInt(rows) == 0) ? 0 : 1));
map.put("total", total);
map.put("current", Integer.parseInt(page));
return map;
}
@RequestMapping("/getByName")
@ResponseBody
public Map getByName(String name) {
TestRedisEntity testRedisEntity = testRedisService.selectByName(name);
Map map = new HashMap();
map.put("redisEntity", testRedisEntity);
return map;
}
@RequestMapping("/get")
@ResponseBody
public Map getTestRedisByName(String name) {
TestRedisEntity testRedisEntity = testRedisService.selectByName(name);
Map map = new HashMap();
map.put("testRedisEntity", testRedisEntity);
return map;
}
@RequestMapping("/insert")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map insertTestRedis(TestRedisEntity testRedisEntity) {
int insert = testRedisService.insert(testRedisEntity);
Map map = new HashMap();
map.put("result", insert);
return map;
}
@RequestMapping("/update")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map updateTestRedis(TestRedisEntity testRedisEntity) {
int update = testRedisService.update(testRedisEntity);
Map map = new HashMap();
map.put("result", update);
return map;
}
@RequestMapping("/deleteById")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map deleteById(String id) {
int deleteById = testRedisService.deleteById(Integer.parseInt(id));
Map map = new HashMap();
map.put("result", deleteById);
return map;
}
@RequestMapping("/deleteByName")
@ResponseBody
@RequiresPermissions(value = "vip")
public Map deleteByName(String name) {
int deleteByName = testRedisService.deleteByName(name);
Map map = new HashMap();
map.put("result", deleteByName);
return map;
}
@RequestMapping("/form")
public String form() {
return "testRedis/form";
}
}
springboot启动类,ShiroTest1Application.java添加自定义序列化类bean,不要这个也可以,但是在redis上看就是\x\x\x之类
package com.xiaostudy.shiro_test1;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@SpringBootApplication
//@MapperScan(basePackages = "com.xiaostudy.shiro_test1.mapper")
public class ShiroTest1Application {
public static void main(String\[\] args) {
SpringApplication.run(ShiroTest1Application.class, args);
}
/\*\*
\* redisTemplate 序列化使用的jdkSerializeable, 存储二进制字节码, 所以自定义序列化类
\* @param redisConnectionFactory
\* @return
\*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON\_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
web.xml
<!--请求编码设置-->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/\*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index</welcome-file>
</welcome-file-list>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>\*.css</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>\*.gif</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>\*.jpg</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>\*.js</url-pattern>
</servlet-mapping>
spring-mvc.xml
<!-- 把Controller交给spring管理 -->
<context:component-scan base-package="com.xiaostudy"/>
<!-- 配置注解处理器映射器 功能:寻找执行类Controller -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!-- 配置注解处理器适配器 功能:调用controller方法,执行controller -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
<!-- 配置sprigmvc视图解析器:解析逻辑试图
后台返回逻辑试图:index
视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/index.jsp -->
<!--<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/"/>
<property name="suffix" value=".jsp"/>
</bean>-->
application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/my_test?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# 初始化时建立物理连接连接的个数
initialSize: 5
# 最小连接池数量
minIdle: 5
# 最大连接池数量
maxActive: 20
# 获取连接时最大等待时间(ms),即60s
maxWait: 60000
# 1.Destroy线程会检测连接的间隔时间;2.testWhileIdle的判断依据
timeBetweenEvictionRunsMillis: 60000
# 最小生存时间ms
minEvictableIdleTimeMillis: 600000
maxEvictableIdleTimeMillis: 900000
# 用来检测连接是否有效的sql
validationQuery: SELECT 1 FROM DUAL
# 申请连接时执行validationQuery检测连接是否有效,启用会降低性能
testOnBorrow: false
# 归还连接时执行validationQuery检测连接是否有效,启用会降低性能
testOnReturn: false
# 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,
# 执行validationQuery检测连接是否有效,不会降低性能
testWhileIdle: true
# 是否缓存preparedStatement,mysql建议关闭
poolPreparedStatements: false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,log4j
thymeleaf:
suffix: .html
charset: utf-8
#清除缓存,实现热部署
cache: false
mvc:
# 配置静态资源映射路径,/public、/resources路径失效
static-path-pattern: templates/**
#redis配置
redis:
host: 127.0.0.1
port: 6379
password:
database: 2
timeout: 3000ms
jedis:
pool:
max-active: 200
max-idle: 100
min-idle: 1
max-wait: 3000ms
mybatis:
mapper-locations: classpath:mapper/*.xml
# mapperLocations: classpath:mapper/*.xml
# 虽然可以配置这项来进行pojo包扫描,但其实我更倾向于在mapper.xml写全类名
# type-aliases-package: com.xiaostudy.shiro_test1.entity
# 后台打印sql
logging:
level:
com.xiaostudy.shiro_test1.mapper : debug
登录页面,login.html
主页,index.html
通过认证后普通用户可以访问,user/index.html
通过认证后,vip用户可以访问,vip/index.html
认证通过后,普通用户访问vip页面时跳转提示没有权限,error/unAuth.html
认证通过后,所有用户可以访问,测试redis主页,testRedis/index.html
<script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script>
<!--jqueryui-->
<link href="//cdn.bootcss.com/jqueryui/1.12.0-rc.2/jquery-ui.min.css" th:href="@{/statics/jquery-ui-1.12.0-rc.2/jquery-ui.min.css}" rel="stylesheet">
<!--jqgrid的css-->
<link href="//cdn.bootcss.com/jqgrid/4.6.0/css/ui.jqgrid.css" th:href="@{/statics/jquery.jqGrid-4.6.0/css/ui.jqgrid.css}" rel="stylesheet">
<!--locale-->
<script src="//cdn.bootcss.com/jqgrid/4.6.0/js/i18n/grid.locale-en.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/i18n/grid.locale-en.js}"></script>
<!--jqgrid的js-->
<script src="//cdn.bootcss.com/jqgrid/4.6.0/js/jquery.jqGrid.min.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/jquery.jqGrid.min.js}"></script>
<link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet">
<script src="" th:src="@{/statics/layui/layui.all.js}"></script>
测试redis主页,添加、修改、查看的form页面,testRedis/form.html
<script src="" th:src="@{/statics/js/jquery-3.0.0.js}"></script>
<!--jqueryui-->
<link href="//cdn.bootcss.com/jqueryui/1.12.0-rc.2/jquery-ui.min.css" th:href="@{/statics/jquery-ui-1.12.0-rc.2/jquery-ui.min.css}" rel="stylesheet">
<!--jqgrid的css-->
<link href="//cdn.bootcss.com/jqgrid/4.6.0/css/ui.jqgrid.css" th:href="@{/statics/jquery.jqGrid-4.6.0/css/ui.jqgrid.css}" rel="stylesheet">
<!--locale-->
<script src="//cdn.bootcss.com/jqgrid/4.6.0/js/i18n/grid.locale-en.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/i18n/grid.locale-en.js}"></script>
<!--jqgrid的js-->
<script src="//cdn.bootcss.com/jqgrid/4.6.0/js/jquery.jqGrid.min.js" th:src="@{/statics/jquery.jqGrid-4.6.0/js/jquery.jqGrid.min.js}"></script>
<link href="" th:href="@{/statics/layui/css/layui.css}" rel="stylesheet">
<script src="" th:src="@{/statics/layui/layui.all.js}"></script>
pom.xml
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- Shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<!-- redis 包 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
数据库表创建
用户表、角色表、权限表、用户与角色多对多表、角色与权限多对多表
DROP TABLE IF EXISTS `role_permission`;
DROP TABLE IF EXISTS `permission`;
DROP TABLE IF EXISTS `user_role`;
DROP TABLE IF EXISTS `role`;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255),
`password` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '用户表';
CREATE TABLE `role` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '角色表';
CREATE TABLE `user_role` (
`id` VARCHAR(255) PRIMARY KEY,
`user_id` VARCHAR(255),
`role_id` VARCHAR(255),
FOREIGN KEY (`user_id`) REFERENCES `user`(id),
FOREIGN KEY (`role_id`) REFERENCES `role`(id)
) engine = InnoDB default charset = utf8 comment = '用户与角色多对多表';
CREATE TABLE `permission` (
`id` VARCHAR(255) PRIMARY KEY,
`name` VARCHAR(255),
`url` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '权限表';
CREATE TABLE `role_permission` (
`id` VARCHAR(255) PRIMARY KEY,
`role_id` VARCHAR(255),
`permission_id` VARCHAR(255),
FOREIGN KEY (`role_id`) REFERENCES `role`(id),
FOREIGN KEY (`permission_id`) REFERENCES `permission`(id)
) engine = InnoDB default charset = utf8 comment = '角色与权限多对多表';
insert into `user` (`id`, `name`, `password`) values('','admin','');
insert into `user` (`id`, `name`, `password`) values('','vip','');
insert into `user` (`id`, `name`, `password`) values('','svip','');
insert into `role` (`id`, `name`) values('','user');
insert into `role` (`id`, `name`) values('','vip');
insert into `role` (`id`, `name`) values('','svip');
insert into `permission` (`id`, `name`, `url`) values('','user','user');
insert into `permission` (`id`, `name`, `url`) values('','vip','vip');
insert into `permission` (`id`, `name`, `url`) values('','svip','svip');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `user_role` (`id`, `user_id`, `role_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
insert into `role_permission` (`id`, `role_id`, `permission_id`) values('','','');
测试redis表
DROP TABLE IF EXISTS `test_redis`;
CREATE TABLE `test_redis` (
`id` int(11) PRIMARY KEY auto_increment,
`name` VARCHAR(255),
`password` VARCHAR(255)
) engine = InnoDB default charset = utf8 comment = '测试redis表';
layui官网下载:https://www.layui.com/
jqGrid官网下载:http://www.trirand.com/blog/?page_id=6
jqueryUI官网下载:http://jqueryui.com/download/all/
jquery下载:http://www.jq22.com/jquery-info122
测试权限的就不在这里重复测试了,可以看一下之前写的文章【直接看最后的测试】:https://www.cnblogs.com/xiaostudy/p/10990999.html
手机扫一扫
移动阅读更方便
你可能感兴趣的文章