shiro 权限登陆
目录结构:
jpa建表 :
权限表:
@Setter
@Getter
@Entity
@Table(name="T_PERMISSION")
@XmlRootElement(name = "permission") //jersey 接受传递对象用
public class Permission {
@Id
@Column(name="ID",length=50,nullable=false)
@GeneratedValue(strategy= GenerationType.IDENTITY)//自增长
@FormParam(value="id") //jersey使用
private Integer id;
//暂时用不到,考虑权限等级管理可能用到
@Column(name="PARE_ID",length=50)
@FormParam(value="pareid")
private Integer pare_id;
@Column(name="PERM_NAME",length=255)
@FormParam(value="permName")
private String permname;
}
角色表
@Getter
@Setter
@Entity
@Table(name="T_ROLE")
@XmlRootElement(name = "role") //jersey 接受传递对象用
public class Role {
@Id
@Column(name="ID",length=50,nullable=false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@FormParam(value="id")
private Integer id;
@Column(name="ROLE_NAME",length=255)
@FormParam(value="roleName")
private String roleName;
@Column(name="note",length=255)
@FormParam(value="note")
private String note;
@ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
@JoinTable(name = "T_PERM_ROLE", joinColumns = { @JoinColumn(name = "role_id") }, inverseJoinColumns ={@JoinColumn(name = "perm_Id") })
private List<Permission> permList;// 一个角色可以有多个权限
}
角色权限表
@Getter
@Setter
@Entity
@Table(name="T_PERM_ROLE")
@XmlRootElement(name = "permRole") //jersey 接受传递对象用
public class PermRole {
@Id
@Column(name = "ID", length = 50, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@FormParam(value = "id")
private Integer id;
@Column(name = "ROLE_ID", length = 255)
@FormParam(value = "roleId")
private Integer roleId;
@Column(name = "PERM_ID", length = 255)
@FormParam(value = "permId")
private Integer permId;
}
用户表
@Getter
@Setter
@Entity
@Table(name="T_USER",uniqueConstraints={@UniqueConstraint(columnNames={"USER_NAME"})})
//建表并指定唯一约束
@XmlRootElement(name = "user") //jersey 接受传递对象用
public class User {
@Id
@Column(name="ID",length=50,nullable=false)
@GeneratedValue(strategy=GenerationType.IDENTITY)
@FormParam(value="id")
private Integer id;
@NotBlank(message = "用户名不能为空")
@Column(name="USER_NAME",length=255)
@Size(min=3, max=20)
@FormParam(value="userName")
private String userName;
@NotBlank(message = "密码不能为空")
@Column(name="PASSWORD",length=255)
@Size(max=100)
@FormParam(value="password")
private String password;
//暂时用不到,网上提到的作用 判断权限是否可用
@Column(name="available",length=1)
@FormParam(value="available")
private Boolean available;
//目前没用到 可装填信息
@Column(name="note",length=255)
@FormParam(value="note")
private String note;
@ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
@JoinTable(name = "T_USER_ROLE", joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns ={@JoinColumn(name = "role_Id") })
private List<Role> roleList;// 一个用户具有多个角色
}
用户角色表
@Getter
@Setter
@Entity
@Table(name="T_USER_ROLE")
@XmlRootElement(name = "userRole") //jersey 接受传递对象用
public class UserRole {
@Id
@Column(name = "ID", length = 50, nullable = false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
@FormParam(value = "id")
private Integer id;
@Column(name = "USER_ID", length = 50)
@FormParam(value = "USER_ID")
private Integer userId;
@Column(name = "ROLE_ID", length = 50)
@FormParam(value = "ROLE_ID")
private Integer roleId;
}
ShiroConfig: 这个类主要是设置拦截权限
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// setLoginUrl 如果不设置值,默认会自动寻找Web工程根目录下的"/login.jsp"页面 或 "/login" 映射
shiroFilterFactoryBean.setLoginUrl("/login");
//未授权跳转界面
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
// 设置拦截器
Map<String, String> filterMap = new HashMap<>();
//不设拦截的链接
filterMap.put("/doLogin", "anon");
filterMap.put("/logout","logout");
System.out.println("执行授权");
//设置角色权限
filterMap.put("/updateUser", "roles[admin]"); // roles用户角色拦截 : 角色符合admin则通过
filterMap.put("/register","perms[save]"); //perms角色权限拦截 : 权限符合save则通过
filterMap.put("/getUser","perms[select]");
//主要这行必须放在所有权限设置的最后,不然所有 url 都会被拦截 //authc:禁止访问,anon:可以访问
filterMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 注入 securityManager
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(customRealm());
return securityManager;
}
/**
* 自定义身份认证 realm;
* <p>
* 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm,
* 否则会影响 CustomRealm类 中其他类的依赖注入
*/
@Bean
public CustomRealm customRealm() {
return new CustomRealm();
}
}
CutomRealm :这个类主要用于 用户登陆认证,权限认证
public class CustomRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 获取用户身份验证信息
* Shiro中,最终是通过 Realm 来获取应用程序中的用户、角色及权限信息的。
* authenticationToken 用户身份信息 token
* @return 返回封装了用户信息的 AuthenticationInfo 实例
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException {
// 拿到用户信息另一方式
// UsernamePasswordToken userToken=new UsernamePasswordToken();
// String username=userToken.getUsername();
// char[] password=userToken.getPassword();
//获取用户的输入的用户名
String username = (String)token.getPrincipal();
//通过username从数据库中查找 User对象
User userInfo = userService.findByUserName(username);
if(userInfo == null){
return null;
}
SimpleAuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(username, userInfo.getPassword(), "" );
return authenticationInfo;
}
// 获取用户角色权限认证
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
System.out.println(principals.getPrimaryPrincipal()+"--------");
String userName = (String) principals.getPrimaryPrincipal(); //获得用户名字
User user= userService.findByUserName(userName); //从数据库查出用户数据
for(Role role:user.getRoleList()){
authorizationInfo.addRole(role.getRoleName()); // add用户角色
for(Permission p:role.getPermList()){
authorizationInfo.addStringPermission(p.getPermname()); //add角色权限
}
}
return authorizationInfo;
}
}
UserContoller
@Controller
public class UserController {
@Autowired
UserService userService;
@GetMapping("/login")
public String notLogin() {
return "test/login";
}
@PostMapping("/doLogin")
public String doLogin(User user, Model model) {
//获得Subject
Subject subject = SecurityUtils.getSubject();
//封装用户数据
System.out.println(user.getUserName()+user.getPassword());
UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(),user.getPassword());
try{
subject.login(token);
return "redirect:/index";
}catch (UnknownAccountException e){
model.addAttribute("msg","用户名不存在");
System.out.println("用户名不存在");
return "test/login";
}catch (IncorrectCredentialsException e){
model.addAttribute("msg","密码不正确");
System.out.println("密码不正确");
return "test/login";
}
}
@GetMapping("/index")
public String index() {
return "test/index";
}
@RequestMapping("/logout") //登陆退出
public String logout(){
return "redirect:/login";
}
@GetMapping("/unAuth") //无权限时候调用
public String unAuth() {
return "test/403";
}
@RequestMapping("/getUser") //查询所有user
public String getAllUser(Model model) {
List<User> users = userService.find();
model.addAttribute("users", users);
return "users";
}
@RequestMapping("/register") //进入注册页面
public String regist() {
return "register";
}
@RequestMapping("/doRegister") //执行注册
public String doRegister(@Valid User user, BindingResult result, Model model) {
String errorMsg = "";
if (result.hasErrors()) {
List<ObjectError> errors = result.getAllErrors();
for (ObjectError e : errors) {
errorMsg = errorMsg + e.getCode() + e.getDefaultMessage();
}
model.addAttribute("errorMsg", errorMsg);
return "register";
}
User user1 = userService.findByUserName(user.getUserName());
if (user1 != null) {
model.addAttribute("errorMsg", "用户名重复");
return "register";
}
// UserParam user=new UserParam();
// BeanUtils.copyProperties(userParam,user);
userService.save(user);
model.addAttribute("msg", "注册成功");
return "success";
}
@GetMapping("/removeUserById") //通过id删除用户
public String removeUserById(HttpServletRequest request) {
String userId = request.getParameter("id");
userService.removeById(Integer.parseInt(userId));
return "redirect:/getUser";
}
@RequestMapping("/updateUser") //跳转更新用户信息页面
public String UpdateUser(User user, Model model) {
model.addAttribute("user",user);
System.out.println(user.getUserName());
return "updateUser";
}
@RequestMapping("/doUpdate") //执行更新
public String doUpdate(User user, Model model) {
User user1 = userService.findByUserName(user.getUserName());
if (user1 != null) {
model.addAttribute("errorMsg", "用户名重复");
model.addAttribute("user",user);
return "UpdateUser";
}
userService.updateUser(user);
return "redirect:/getUser";
}
}
Dao 层
public interface UserDao extends JpaRepository<User, Integer> {
//查询用户通过密码和姓名
User findByUserNameAndPassword(String username, String password);
//查询所有用户
@Query(value="select u.* from user u", nativeQuery = true)
List<User> find(); //用findAll 为方法名则可以不写注解
//保存一条用户
User save(User user);
//根据名字查询用户
User findByUserName(String userName);
@Transactional
void removeById(Integer Id);
@Transactional
@Query(value = "update t_user set user_name=?1,password=?2 where id=?3", nativeQuery = true)
@Modifying
public void updateOne(String userName,String password,Integer id);
}
Service层
@Service
public class UserService {
@Autowired
UserDao userDao;
public User getUser(String username, String password) {
return userDao.findByUserNameAndPassword(username,password);
}
public List<User> find(){
return userDao.findAll();
} //查询所有用户
public void save(User user){
userDao.save(user);
} //存储一个用户
public User findByUserName(String userName){ //根据用户名查询用户信息
return userDao.findByUserName(userName);
}
public void removeById(Integer id){ userDao.removeById(id); //移除一个用户
}
public void updateUser(User user){
userDao.updateOne(user.getUserName(),user.getPassword(),user.getId());
} //更新用户的 密码 ID
}
jerseyConfig (在这个项目中无意义 前后端分离模式可用)
@Component
@ApplicationPath("/rest")
public class JerseyConfig extends ResourceConfig{
public JerseyConfig(){
//注册请求的上下文文件
//register(RequestContextFilter.class);
//注册类方式 register(WSSayHellokitty.class);
//包扫描
packages("com.example.ws");
packages("com.example.Controller");
}
}
403.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>小伙汁,你的权限够不够哦</h1>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
index
<br>
<h1>欢迎光临首页</h1>
<br>
update<a href="/updateUser">更新用户</a><br>
insert<a href="/register">注册用户</a><br>
select<a href="/getUser">查询所有用户</a><br>
<br>
insert<a href="/logout">退出登录</a><br>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
</head>
<body class="text-center">
<div >
<h1>221</h1>
<h2 style="color: red" th:text="${msg}"></h2>
<form name="form" accept-charset="utf-8" action="/doLogin" method="post">
<ul >
<li>
<label class="input-tips2">用户名:</label>
<div>
<input type="text" id="username" name="userName" maxlength="16" />
</div>
</li>
<li>
<label class="input-tips2">密码:</label>
<div >
<input type="password" id="password" name="password" maxlength="16"/>
</div>
</li>
<li>
<div >
<input type="submit" value="登录"/>
<a href="/register">注册</a>
</div>
</li>
</ul>
</form>
</div>
<h1><asadadas></asadadas></h1>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="margin:0 auto;background-color: antiquewhite;width: 500px;height: 600px;">
<h1 th:text="${errorMsg}"></h1>
<form action="/doRegister" method="post"/>
<label>请输入姓名</label><input type="text" name="userName"/><br>
<label>请输密码</label><input type="text" name="password"/>
<input type="submit" value="提交"/>
</form>
</div>
</body>
</html>
seccuss.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
<span th:text="${msg}"></span>
<a href="/getUser"><button> 点击查询所有人</button></a>
<h1 th:text="id+${id}"></h1>
<h1 th:text="name+${name}"></h1>
</body>
</html>
updateUser.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
<span th:text="${msg}"></span>
<a href="/getUser"><button> 点击查询所有人</button></a>
<h1 th:text="id+${id}"></h1>
<h1 th:text="name+${name}"></h1>
</body>
</html>
users.html
<!DOCTYPE html>
<html lang="en" xmlns="http://www.thymeleaf.org" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script>
</script>
<body>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td></br>
<td th:text="${user.userName}">1</td><br>
<td th:text="${user.password}">1</td> <br>
<a th:href="@{/removeUserById?(id=${user.id})}"><button>点击删除</button></a><br>
<form id="form" action="/updateUser" method="post">
<input type="hidden" name="id" th:value="${user.id}"/>
<input type="hidden" name="UserName" th:value="${user.userName}" />
<input type="hidden" name="password" th:value="${user.password}" />
<input type="submit" value="修改" /><br>
</form>
</tr>
<a> </a>
</body>
</html>
application.yml
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/peimenghao
username: root
password: root
jpa:
database: MYSQL
hibernate:
ddl-auto: update
show-sql: true
收获: jpa 建表策略
shiro 简单的配置使用
踩了两天坑 ,到处查资源总算跑出理想效果了。
简洁易用!!